首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >常量%1是否被截断为整数?

常量%1是否被截断为整数?
EN

Stack Overflow用户
提问于 2014-08-31 00:07:26
回答 4查看 1.7K关注 0票数 3

为什么这段代码不能编译?

代码语言:javascript
运行
复制
package main
const a = 1.000001
const base = 0
const b = a+base
func main() {
    f(b)
}
func f(int) {}
代码语言:javascript
运行
复制
$ go run a.go
# command-line-arguments
./a.go:4: constant 1 truncated to integer

它是说1被截断了?或者说1不能被截断?它说的是哪一个?

有人回答说上面的代码不能编译,因为b是一个float64。但是为什么会这样编译呢:

代码语言:javascript
运行
复制
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) {}
代码语言:javascript
运行
复制
$ go run a.go 
float64 1.000001
float64 1

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

EN

回答 4

Stack Overflow用户

发布于 2014-08-31 01:03:07

go团队最近做了一个blog post about this,我建议你读一读。

从引言

Go是一种静态类型语言,不允许混合数字类型的操作。不能将float64添加到int,甚至不能将int32添加到int。然而,编写1e6*time.Second或math.Exp(1)甚至1<<('\t'+2.0)是合法的。在Go中,常量与变量不同,其行为与常规数字非常相似。这篇文章解释了为什么会这样,以及它的含义。

TLDR -常量在Go中是无类型的。他们的类型只是在最后一刻才被具体化。

这就解释了你上面的问题。给定的

代码语言:javascript
运行
复制
func f(int) {}

然后

代码语言:javascript
运行
复制
f(1) // ok
f(1.000) // OK
f(1.0E6) // OK
f(1.0001) // BAD
票数 7
EN

Stack Overflow用户

发布于 2014-08-31 01:07:34

Go有常量的very strict conversion rules

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

  • x可由T.
  • x类型的值表示,T是浮点类型,x可由使用IEEE754四舍五入规则舍入后的T类型的值表示。常量value.
  • x是整数常量,T是字符串类型,常量是四舍五入的T(x)。与非常数x相同的规则也适用于这种情况。

golang blog post about constants可能有助于进一步理解这一点。由于严格性,每个违反引用规则的转换都被认为是错误的。这背后的原因是Go试图尽可能准确地表示常量。这也意味着最终的类型是在所使用的表达式的上下文中决定的。抛开精确度,这是一个可能的编程错误的标志。

如果您确实希望将值四舍五入为整数,请将其转换为变量(Example on play):

代码语言:javascript
运行
复制
const b = 1.01
c := b
f(int(c))

这是因为编译器不会跟踪值的来源和不适用于变量的常量规则。

但是为什么当我把它改成这样的时候它还能起作用呢?const a = 1.000001;const b = a-0.000001

在本例中,b等于1.1。1可以表示为整数,因此不涉及舍入和信息丢失。因此,这不是一个错误,因为它符合浮点值的转换规则(如前所述)。

票数 4
EN

Stack Overflow用户

发布于 2014-09-03 21:21:12

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

代码语言:javascript
运行
复制
package main
func main() {
    f(1.000001)
}
func f(int) {}

它显然没有将整数值传递给整数函数。

您的第二个程序可以类似地重写如下:

代码语言:javascript
运行
复制
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) {}

看起来挺好的。

我所做的就是手动替换ab常量。这就是go所做的一切。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25584329

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档