对于int8 var,如何理解“ -128 / -1”和“ -128 * -1”的结果是-128?

问题描述

几周前才开始学习Go,这种行为令我非常困惑。

var n int8 = -128

n /= -1
fmt.Println(n)

n *= -1
fmt.Println(n)

以上code都将输出-128。我还尝试了-64 * -2,这也导致了-128

-128的值是否特殊,这意味着int 溢出

解决方法

这不是在溢出时使用的特殊值,它只是一个带符号的8位整数的最小值(有效范围为[-128,128),表示包括-128,但不包括-128)。 / p>

在简单的情况下,例如增加最大值(例如:int8(127) + 1),您会使整数溢出并以最小值结尾。

在Go语言中,这是完全可以接受的,正如spec

所述

对于有符号整数,可以合法地使用+,-,*,/和

但是您的具体情况有所不同,这是由于取最大负值的2的补码会返回相同的值

最简单的例子是这个例子:

    var n int8 = -128
    fmt.Println(-n)
    // output -128

这是因为翻转所有位并加1将返回完全相同的内容:

  // Start with -128
  n = 1000 0000
  // Flip bits:
  n = 0111 1111
  // Add 1:
  n = 1000 0000

糟糕!这意味着-(-128) == -128

乘法和除法也是如此:-1 * (-128) == -128。 在除法的情况下,某些语言的结果不确定。 Go spec并没有说明这种歧义,而是说明了这种特殊情况:

...如果红利x最大 x的int类型为负值,商q = x / -1等于 由于二进制补码整数溢出而导致x变为x(且r = 0)

您可以在Wikipedia上找到有关二进制补码算术的更多信息,该节专门介绍the most negative number