Today we continue our discussion of arithmetic operators, with a topic that is likely not new to you at all: Integer operators.
Integer operators
For two integer values
x
andy
, the integer quotientq = x / y
and remainderr = x % y
satisfy the following relationships:x = q*y + r and |r| < |y|
This should be pretty obvious and intuitive… If you divide x / y
and get a quotiont q
and remainder r
, then multiplying q * y
and adding r
should reveal x
again.
with
x / y
truncated towards zero (“truncated division”).x y x / y x % y 5 3 1 2 -5 3 -1 -2 5 -3 -1 2 -5 -3 1 -2
This should also be unsurprising. If x
does not divide evenly into y
, then division is truncated toward zero, as in virtually every other language. (Or at least those with the concepts of an integer… Sorry JavaScript.)
The one exception to this rule is that if the dividend
x
is the most negative value for the int type ofx
, the quotientq = x / -1
is equal tox
(andr = 0
) due to two’s-complement integer overflow:x, q int8 -128 int16 -32768 int32 -2147483648 int64 -9223372036854775808
Integer overflow is annoying, and it gives us the one exception to this rule. Why is this?
Let’s have a look…
var x = int8(-128)
fmt.Println(x/-1) // -128, as explained above
What is the “correct” answer? Well, 128, as we can see if we use a larger integer type:
var x = int16(-128)
fmt.Println(x/-1) // 128
But there’s no way to represent the value int8
as an int8
because of integer overflow. The valid values for an int8
are -128
through 127
. In fact, if you try to represent 128
as an int8
, you’ll get -127
, regardless of whether you arrive at that value via division or some other means:
var y = int16(128)
fmt.Println(int8(y)) // -128
So converting from int16(128)
to int8
gives us -128
.
var z = int8(127)
fmt.Println(z+1) // -128
And adding 1
to int8(127)
also gives us -128
.
So this special case isn’t quite so special after all.
Quotes from The Go Programming Language Specification Version of August 2, 2023