Go integer overflow settings in commandline and playground

huangapple go评论90阅读模式
英文:

Go integer overflow settings in commandline and playground

问题

这个程序在我的机器上运行良好(go1.2.1 linux/amd64):

package main

import "fmt"

const bigint = 1<<62

func main() {
    fmt.Println(bigint)
}

但是在 Go Playground 上运行时,会出现溢出错误 - http://play.golang.org/p/lAUwLwOIVR

看起来我的构建配置为整数常量使用了 64 位,而 Playground 配置为 32 位。

但是规范中说实现必须至少给常量提供 256 位的精度?

另请参阅我的另一个问题中的代码 - scanner 标准包中的代码:

const GoWhitespace = 1<<'\t' | 1<<'\n' | 1<<'\r' | 1<<' '

由于空格是 32,这在 32 位的 Playground 上根本无法工作。

这是怎么回事?

英文:

This program runs fine one my machine (go1.2.1 linux/amd64):

package main

import &quot;fmt&quot;

const bigint = 1&lt;&lt;62

func main() {
    fmt.Println(bigint)
}

But with the go playground, it gives overflow error - http://play.golang.org/p/lAUwLwOIVR

It seem that my build is configured with 64 bits for integer constans, playground configured with 32 bits.

But spec say that implementation must give at least 256 bits of precision for constants?

Also see code in my other question -- the scanner standard package has code:

const GoWhitespace = 1&lt;&lt;&#39;\t&#39; | 1&lt;&lt;&#39;\n&#39; | 1&lt;&lt;&#39;\r&#39; | 1&lt;&lt;&#39; &#39;

Since space is 32, this don't work on 32-bit playground at all.

How can this be?

答案1

得分: 4

一般常量

常量本身在精度上没有限制,但在代码中使用时会转换为适当的类型。根据规范

常量可以通过常量声明或转换显式地指定类型,也可以在变量声明、赋值或表达式中隐式地指定类型。 如果常量值无法表示为相应类型的值,则会出现错误。例如,3.0 可以赋给任何整数或浮点类型,而 2147483648.0(等于 1<<31)可以赋给 float32、float64 或 uint32 类型,但不能赋给 int32 或 string 类型。

因此,如果你有以下代码:

const a = 1 << 33
fmt.Println(a)

你将会得到一个溢出错误,因为整数常量的默认类型 int32 位环境中无法容纳值 1 << 33。如果你将常量转换为 int64,在所有平台上都没有问题:

const a = 1 << 33
fmt.Println(int64(a))

Scanner

常量 GoWhitespace 并未直接在扫描器中使用。在 Scanner 类型中使用的 Whitespace 属性uint64 类型,而 GoWhitespace 被赋值给它

s.Whitespace = GoWhitespace

这意味着你处理的是一个 uint64 值,而 1 << ' '(即 1 << 32)是完全有效的。

示例(在 play 上):

const w = 1<<'\t' | 1<<'\n' | 1<<'\r' | 1<<' '

c := ' '

// fmt.Println(w & (1 << uint(c))) // 会导致溢出错误
fmt.Println(uint64(w) & (1 << uint(c))) // 正常工作
英文:

Constants in general

Constants itself are not limited in precision but when used in code they are converted to a suitable type.
From the spec:

> A constant may be given a type explicitly by a constant declaration or conversion, or implicitly when used in a variable declaration or an assignment or as an operand in an expression. It is an error if the constant value cannot be represented as a value of the respective type. For instance, 3.0 can be given any integer or any floating-point type, while 2147483648.0 (equal to 1<<31) can be given the types float32, float64, or uint32 but not int32 or string.

So if you have

const a = 1 &lt;&lt; 33
fmt.Println(a)

you will get an overflow error as the default type for integer constants int can't hold the value 1 &lt;&lt; 33 on 32 bit environments. If you convert the constant to int64 everything's fine on all platforms:

const a = 1 &lt;&lt; 33
fmt.Println(int64(a))

Scanner

The constant GoWhitespace is not directly used in the scanner.
The Whitespace attribute used in the Scanner type is of type uint64 and GoWhitespace is assigned to it:

s.Whitespace = GoWhitespace

This means you deal with a uint64 value and 1 &lt;&lt; &#39; &#39; (aka. 1 &lt;&lt; 32) is perfectly valid.

Example (on play):

const w = 1&lt;&lt;&#39;\t&#39; | 1&lt;&lt;&#39;\n&#39; | 1&lt;&lt;&#39;\r&#39; | 1&lt;&lt;&#39; &#39;

c := &#39; &#39;

// fmt.Println(w &amp; (1 &lt;&lt; uint(c))) // fails with overflow error
fmt.Println(uint64(w) &amp; (1 &lt;&lt; uint(c))) // works as expected

答案2

得分: 1

根据nemo的说法,你可以给常量指定一个类型。只需指定int64,它就可以正常工作 Go integer overflow settings in commandline and playground

package main

import "fmt"

const bigint int64 = 1<<62

func main() {
    fmt.Println(bigint)
}

链接:http://play.golang.org/p/yw2vsvMigk

英文:

As stated by nemo, you can give a type to your constant. Just specify int64 and it works fine Go integer overflow settings in commandline and playground

http://play.golang.org/p/yw2vsvMigk

package main

import &quot;fmt&quot;

const bigint int64 = 1&lt;&lt;62

func main() {
    fmt.Println(bigint)
}

huangapple
  • 本文由 发表于 2014年3月17日 00:42:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/22439698.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定