为什么两个正整数的乘积是负整数?

时间:2017-09-28 14:42:30

标签: integer-overflow systems-programming

本学期我参加了系统学习课程。 为什么50000 * 50000会消极? 我试着理解这个的逻辑。 这是幻灯片的屏幕截图

slide image

3 个答案:

答案 0 :(得分:1)

通过使用位0-30作为数字来存储32位有符号整数,并使用位31来指示数字的符号。

这意味着可以表示的最大值是2,147,483,647(设置0-30的所有位,位31是0表示正数)。

50,000和50,000的产品是25,000,000,000大于这个数字,你有所谓的溢出。这意味着数据已经从其预期的边界(底部的31位)“溢出”到符号位。)

您现在设置了第31位,表示这是一个负数。要从二进制表示中找出一个负数,你可以选择一个补码(翻转所有位),加一个,然后在它前面加一个负号。

当你把自己限制在32位范围内的那些补码时要小心......你不应该包括高于第31位的位。

查看signed number representations了解详情。

答案 1 :(得分:1)

示例程序伪代码

Print --> ("Size of int: " + (Integer.SIZE/8) + " bytes.");
int a=50000;
int b=50000;
Print --> (" Product of a and b " + a*b);   

Output :
Size of int: 4 bytes. 
Product of a and b:-1794967296

分析: 4字节= 4 * 8 = 32位。

由于signed int可以保存负值,因此一位用于符号( - 或+),因此可用于数值范围的位= 31。 数字范围= - (2 ^ 31),0和(2 ^ 31-1) [一个正数被牺牲为0]

-2147483648,0和2147483647

最大可能正int = 2147483647(大于1600000000,所以40000 * 40000很好) 实际产品50000 * 50000 = 2500000000(大于2147483647)

实际上,许多可移植的C程序都假设有符号整数溢出使用二进制补码算法可靠地回绕。 然而,C标准表明程序行为在溢出时是不确定的,并且在少数情况下,C程序不适用于某些现代实现,因为它们的溢出不会像作者所期望的那样包围。 http://www.gnu.org/software/autoconf/manual/autoconf-2.62/html_node/Integer-Overflow.html

答案 2 :(得分:0)

这是因为在大多数编程语言中,整数数据类型具有固定的大小。

这意味着每个整数值都有一个定义的MIN和MAX值。

例如在C#MAX INT中是2147483647,MIN是-2147483648 在PHP 32位中,它是2147483647和-2147483648 在PHP 64位,它是9223372036854775807和-9223372036854775808

当你试图超过这个价值时会发生什么?只需计算机将产生所谓的整数溢出,该值将循环回最小值。

换句话说,在C#2147483647 + 1 = -2147483648(假设您使用整数数据类型,不是long或float)。这正是50000 * 50000所发生的情况,它只是超过最大值并从下一个值开始循环。

确切的最小值和最大值取决于所使用的语言,构建代码的平台,运行代码的平台以及值的静态类型。

希望它为你清除一切!