How is it still possible to calculate 1<<64-1 without issuing an overflow?

Asked

Viewed 100 times

0

The uint64 limit is (2 64)-1, or simply 1<<64-1. When you try to do something like fmt.Print(uint64(1<<64-1)) it works normally, makes sense once it’s within the limit.

However, if the 1<<64 exceeds the limit, as it is still possible to calculate the 1<<64-1, without the use of big.Int and the like?

My question is how is it possible to do:

fmt.Print(uint64(1<<65-1<<64-1))

If the 1<<65 exceeds the limit of uint64, in what format is this? There is a specific name for it?

2 answers

1


Note that there is an optimization and the compiler folda all this for the number of the result and does not perform anything, it is the same as writing the literal number, which is always a constant. If you put a simple variable already screws:

package main
import "fmt"

func main(){
    x := uint32(64)
    fmt.Print(uint64(1 << 65 - 1 << x - 1))
}

Behold nay working in the ideone. And in the repl it.. Also put on the Github for future reference.

Then transforming into a constant value is possible to work this way according to the specification, which I consider to be a mistake because it changes the semantics for no apparent reason, hence the question is very pertinent. There must be a reason, but for me constant should have the same semantics of the variable except for the fact that its value never changes and allow some optimization.

1

This is because the value 1<<65-1<<64-1) is not treated as a uint64 during the execution, but as a Constant Expression during the compilation, and may contain only Constants.

According to the specification:

Constant Expressions are Always evaluated Exactly; Intermediate values and the constants themselves may require Precision significantly Larger than supported by any predeclared type in the language.

Free translation:

Constant Expressions are always calculated accurately; intermediate values and constants themselves may require a significantly greater precision than any type declared by language.

According to the language specification, such constants (of the whole type) must be represented with at least 256 bits. The current version of the language supports an accuracy of up to 512 bits. If an operation is made that exceeds this limit, an error will be thrown. Example:

fmt.Print(uint64(1 << 512))

The above section generates the following error: shift count too large: 512.

If the result of Constant Expression is a value greater than the supported or different from the declared type, the compiler will identify this as an error.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.