I have try to write one logic is to convert an int32
positive value to a corresponding negative one, i.e., abs(negativeInt32) == positiveInt32
.
I have tried with both:
First:
fmt.Printf("%v
", int32(^uint32(int32(2) -1)))
This results in an error : prog.go:8: constant 4294967294 overflows int32
Second:
var b int32 = 2
fmt.Printf("%v
", int32(^uint32(int32(b)-1)))
This results in -2
.
How can both result in different results. I think they are equal.
play.golang.org
Edit for replacing uint32
with int32
for the first situation.
For those who come to this problem, I have answered the question myself. :)
The two results are different because the first value is typecast to an unsigned int32 (a uint32
).
This occurs here: uint32(^uint32(int32(2) -1))
Or more simply: uint32(-2)
An int32
can store any integer between -2147483648 and 2147483647.
That's a total of 4294967296 different integer values (2^32... i.e. 32 bits).
An unsigned int32 can store the same amount of different integer values, but drops the signage (+/-). In other words, an unsigned int32 can store any value from 0 to 4294967295.
But what happens when we typecast a signed int32 (with a value of -2) to an unsigned int32, which cannot possibly store the value of -2?
Well as you have found, we get the value of 4294967294. Which in a number system where one integer less than 0 is 4294967295; 4294967294 happens to be the sum of 0 - 2.
Occasionally, i have learned that why we can not do
fmt.Printf("%v
", int32(^uint32(int32(2) -1)))
at compile time. It is that ^uint32(int32(2)-1)
is treated as a constant
value with uint32
type. It's value is 4294967294
. This exceeds the maximum value of int32
for 2147483647
. So when you run go build
on the source code file. Compile error
is shown.
The right answer to this should be:
fmt.Printf("%v
, ^(int32(2) - 1))
i.e., we should first get the corresponding value of 1
in int32
type and, then convert it to the two's complementary form
as value of -1
.
However, according to this golang blog's An exercise: The largest unsigned int
section, this is legal in runtime. So the code
var b int32 = 2
fmt.Printf("%v
", int32(^uint32(int32(b)-1)))
is alright.
And, finally it comes to that this is related to constants in Golang. :)