Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Go integer overflow settings in commandline and playground

Tags:

go

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

package main

import "fmt"

const bigint = 1<<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<<'\t' | 1<<'\n' | 1<<'\r' | 1<<' '

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

How can this be?

like image 461
zlatanski Avatar asked Mar 16 '14 16:03

zlatanski


Video Answer


2 Answers

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 << 33
fmt.Println(a)

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

const a = 1 << 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 << ' ' (aka. 1 << 32) is perfectly valid.

Example (on play):

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

c := ' '

// fmt.Println(w & (1 << uint(c))) // fails with overflow error
fmt.Println(uint64(w) & (1 << uint(c))) // works as expected
like image 110
nemo Avatar answered Oct 29 '22 18:10

nemo


As stated by nemo, you can give a type to your constant. Just specify int64 and it works fine :)

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

package main

import "fmt"

const bigint int64 = 1<<62

func main() {
    fmt.Println(bigint)
}
like image 37
creack Avatar answered Oct 29 '22 16:10

creack