Types 常数1被截断为整数?

Types 常数1被截断为整数?,types,go,weak-typing,Types,Go,Weak Typing,为什么这段代码不能编译 package main const a = 1.000001 const base = 0 const b = a+base func main() { f(b) } func f(int) {} 是说1被截断了?或者1不能被截断?它说的是哪一个1 有人回答说上面的代码没有编译,因为b是float64。但为什么要编译: package main import "fmt" const a = 1.000001 const b = a-0.000001 func

为什么这段代码不能编译

package main
const a = 1.000001
const base = 0
const b = a+base
func main() {
    f(b)
}
func f(int) {}
是说1被截断了?或者1不能被截断?它说的是哪一个1

有人回答说上面的代码没有编译,因为
b
float64
。但为什么要编译:

package main
import "fmt"
const a = 1.000001
const b = a-0.000001
func main() {
    fmt.Printf("%T %v\n",a,a)
    fmt.Printf("%T %v\n",b,b)
    f(b)
}
func f(int) {}

?
b
在这里是一个
float64
,但它可以传递到
f

免责声明:我对Go没有任何经验,但下面的答案基于与数据类型相关的一般原则

函数
f
采用类型为
int
的输入参数,但传递给它的实际值,即
b
具有基于代码的浮点值。这将导致将浮点值截断为整数值,如错误消息所述

我相信您可以通过更改函数签名来解决这个问题,将浮点类型值作为输入参数,即

func f(float64) {}

要将其与我熟悉的语言(C#)进行比较,您可以查看以下代码:

public static void Main(string[] args)
    {
        var a = 1.3;
        var b = 1.3 + 9;
        f(b);
        Console.WriteLine("Hello, world!");
    }

public static void f(int a)
    {
    }
使用
var
关键字,我们没有显式地将
a
b
变量设置为数据类型
double
。但是,由于浮点值被分配给它们,因此它们的类型被推断为
double
。现在,如果将方法
f
定义为获取数据类型
int
的输入参数,然后传入
a
b
。它会给你一个错误。但是,如果将方法更改为采用
double
值而不是
int
,则代码将编译而不会出现问题

围棋小组最近做了一个报告,我建议您阅读

从介绍开始

Go是一种静态类型语言,不允许 混合数字类型。不能将浮点64添加到int,甚至不能将浮点32添加到int 但写入1e6*time.Second或math.Exp(1)或 即使是1Go也有常数:

在以下任何情况下,常量值x可转换为T型:

  • x
    可由类型为
    T
    的值表示
  • x
    是浮点常量,T是浮点类型,x在使用IEEE 754四舍五入后可由
    T
    类型的值表示 公平规则。常数
    T(x)
    是四舍五入值
  • x
    是整数常量,
    T
    是字符串类型。与非常量
    x
    相同的规则适用于这种情况
这可能有助于进一步理解这一点。 由于严格性,每个违反引用规则的转换都被视为错误。这背后的原因是Go试图尽可能准确地表示常量。这也意味着最终类型是在所用表达式的上下文中确定的。丢掉精度会使这一点失效,这是可能出现编程错误的标志

如果确实要将值舍入为整数,请将其转换为变量():

这是因为编译器不会跟踪值和常量规则的来源,从而不应用于变量


但是为什么我把它改成这个呢<代码>常数a=1.000001;常数b=a-0.000001
在本例中,
b
等于1。1可以表示为整数,因此不涉及舍入和信息丢失。因此,这不是错误,因为它符合浮点值的转换规则(如前所述)。

您的第一个程序可以这样重写:

package main
func main() {
    f(1.000001)
}
func f(int) {}
package main
import "fmt"
func main() {
    fmt.Printf("%T %v\n",1.000001,1.000001)
    fmt.Printf("%T %v\n",1,1)
    f(1)
}
func f(int) {}
这显然不是将整数值传递给整函数

您的第二个程序也可以这样重写:

package main
func main() {
    f(1.000001)
}
func f(int) {}
package main
import "fmt"
func main() {
    fmt.Printf("%T %v\n",1.000001,1.000001)
    fmt.Printf("%T %v\n",1,1)
    f(1)
}
func f(int) {}
看起来不错


我所做的只是手动替换
a
b
常量。这就是我要做的一切。

但是当我把它改成这个时,为什么它能工作呢<代码>常数a=1.000001;const b=a-0.000001同样,我没有围棋的经验,所以你应该得到第二个意见,但我认为1.000001-0.000001=1.000000被视为整数1,它满足
int
参数要求。有趣的是,
reflect.TypeOf(b)
显示
float64
,但
PrintLn(b)
显示1和
reflect.TypeOf(1)
显示
int
@shree.pat18这是因为常量值的计算涉及浮动,因此内部表示仍然是
float64
。但是结果是完全可转换的,所以这里没有错误。你是说
f
得到1.000001?在我看来,非类型化常量
b
被截断为1(因此错误“常量1被截断为整数”),这将使其可以表示为int。如果我将
b
更改为1.2,则错误为“常量1.2被截断为整数”。很明显,这里发生了更多的事情。它说,如果要编译,1.000001将需要被截断。换句话说,非类型化值1.000001不能用int类型表示。在第二个示例中,1.000001-0.000001是值1。您可以按自己喜欢的方式编写它(0x1、1.0等),但这不会改变它的内容。1可以用整数表示,因此可以编译。如果
a=1.000001
,则表示“常数1被截断为整数”。如果我将
a
b
更改为1.2,则错误为“常数1.2截断为整数”。很明显,这里发生了更多的事情。在一种情况下,它报告被截断的版本,而在另一种情况下,它不报告。
const b = 1.01
c := b
f(int(c))
package main
func main() {
    f(1.000001)
}
func f(int) {}
package main
import "fmt"
func main() {
    fmt.Printf("%T %v\n",1.000001,1.000001)
    fmt.Printf("%T %v\n",1,1)
    f(1)
}
func f(int) {}