Location>code7788 >text

Go: Untyped Int Constants and Large Integers

Popularity:164 ℃/2024-11-07 17:36:04

Run the code below:

Click to view code
package main

import "fmt"

const (
	Big = 1 << 100
)

func needFloat(x float64) float64 {
	//("%T", Big)  // It is wrong!
	return x * 0.1
}

func main() {
	(needFloat(Big))  // 1.2676506002282295e+29
}

When I try to print the type of variable Big, an error is reported as follows:

./:10:19: cannot use Big (untyped int constant 1267650600228229401496703205376) as int value in argument to (overflows)

The reasons are as follows:
image
One aspect is that passing a Big value to any function requires that it be assigned an actual type. An untyped int can be turned into any integer type or any floating-point type (depending on the type of the function's arguments.) The largest actual type a single integer value can have in Go is uint64, but the rules for any type (i.e., the type of its arguments) are more specific. They convert untyped int without any other type information to int, which is 64-bit on current CPU architectures. This is well below 1<<100.
image
You may now be wondering "Why do we even have large constants?" The answer is that you can use large (and similarly sized values) in constant expressions. These are evaluated at compile time, and you only get the actual type (roughly speaking) when you use their values.
So you could have const Small=Big>>100, which is equivalent to const Small=1, for example, and use that constant because its value can easily be put into an int.
For example, one area that arises in practice is the calculations required to compute the distances between points on the surface of the Earth. The large number of expressions used there can be computed constantly, which means that there is less loss of precision than assigning the values involved to float64 and doing math on them (since the precision of floating point constants is infinite).