为啥最大负整数-2147483648的绝对值还是-2147483648?

Posted

技术标签:

【中文标题】为啥最大负整数-2147483648的绝对值还是-2147483648?【英文标题】:Why the absolute value of the max negative integer -2147483648 is still -2147483648?为什么最大负整数-2147483648的绝对值还是-2147483648? 【发布时间】:2012-06-28 10:51:10 【问题描述】:

abs(-2147483648) 的结果是-2147483648,不是吗? 这似乎是不可接受的。

printf("abs(-2147483648): %d\n", abs(-2147483648));

输出:

abs(-2147483648): -2147483648

【问题讨论】:

我相信这是未定义的行为。我手边没有 C 标准,所以无法备份。 鉴于abs(int) 返回int,您期望它是什么? C11 的最新草案说(7.21.6.1,关于abs 和朋友)“如果结果无法表示,则行为未定义” @PhilipKendall 绝对值可以是负值吗? linux 手册页说(man 3 abs):没有定义试图取最大负整数的绝对值。 【参考方案1】:

标准说abs()

abslabsllabs 函数计算整数 j 的绝对值。如果结果无法表示,则行为未定义。

结果确实无法表示,因为有符号整数的 2 的补码表示不是对称的。想想看……如果你在 int 中有 32 位,这会给你从 INT_MININT_MAX 的 232 个不同的值。这是偶数个值。因此,如果只有一个 0,则大于 0 的值的数量不能与小于 0 的值的数量相同。因此,对于值为 -INT_MININT_MIN 没有正对应项。

所以,在您的平台上调用abs(INT_MIN) 是不可接受的。

【讨论】:

【参考方案2】:

负数通常用二进制补码表示。

要将正数转换为负数,使用逻辑

x -> not(x)+1

对于 8 位算术

01111111b 是 127 和 -127 变成 10000000b + 1 = 10000001b

和相反的方向 -127 10000001b 变成 01111110b + 1 = 01111111b

-128 怎么样?

-128 是 10000000b 并且没有正数对应物,因为在 8 位有符号算术中没有 128。

10000000 -> 01111111 + 1 = 10000000 和 -128 再次

同样适用于原始问题

【讨论】:

这就是为什么0和最小值在二进制补码中取反后总是相同的原因【参考方案3】:

由于在您的实现中 2147483648 大于 INT_MAX,因此 abs(-2147483648) 未定义。

【讨论】:

【参考方案4】:

这是 GNU glibc 源代码中 abs.c 中的代码。

/* Return the absolute value of I.  */
int
DEFUN(abs, (i), int i)

  return(i < 0 ? -i : i);

所以,abs(-2147483648) 返回 -(-2147483648) 。在x86中,就是通过这两条指令来实现的

movl    $-2147483648, %eax
negl    %eax

negl 指令是这样实现的: 数=0-数; sbb是这样实现的: 从目标中减去源,如果设置了进位标志,则额外减去 1。 所以 abs(-2147483648) (hex is 0x80000000 ) --> -(-2147483648) --> 0-(-2147483648) 最后变成了 (0x80000000)。

negl指令的详细信息,请 访问http://zsmith.co/intel_n.html#neg

sbb指令详情,请访问http://web.itu.edu.tr/kesgin/mul06/intel/instr/sbb.html

【讨论】:

【参考方案5】:

试试这个

printf("abs(-2147483648): %u\n", abs(-2147483648));

【讨论】:

我的朋友,这有未定义的行为。您正在使用无符号格式化程序打印一个有符号整数。我 -1 因为它还没有回答问题。

以上是关于为啥最大负整数-2147483648的绝对值还是-2147483648?的主要内容,如果未能解决你的问题,请参考以下文章

leetcode 7

使用 if_abs 将负整数转换为正数 [重复]

输出两个非负整数的最大公约数

为啥 Go 没有计算整数绝对值的函数?

margin重合问题(转载)

java中Math.abs(-2147483648)的返回值应该是什么?