此问题已在此处有答案:
What is an integer overflow error?(10个答案)
上个月关门了。
#include <stdio.h>
int main(void)
{
unsigned sum = 0;
for (unsigned i = 1; i <= 100000; i++)
{
sum += i;
}
printf("%lld", sum);
return 0;
}
输出:705082704
但正确答案应该是5000050000
3条答案
按热度按时间szqfcxe21#
你的机器上的无符号整数类型几乎肯定是32位的。此类型可以容纳的最大数字是
4294967295
。预期结果大于此值,因此发生整数溢出。解决方案是为
sum
使用更大的数据类型。如果包含
<stdint.h>
,则可能希望使用uint64_t
,使其具有18446744073709551615
的最大潜在值。正如ikegami所指出的,在打印
uint64_t
值时,您还需要提供正确的格式说明符。通常情况下,您会使用%llu
而不是%lld
。为了确保获得正确的说明符(有很多),可以包含<inttypes.h>
并使用PRIuN
系列宏。它们列在前面链接的页面上。例如
如果这对C初学者来说很奇怪,
PRIu64
预处理器宏会插入字符串文字"llu"
,编译器会将相邻的字符串文字视为一个连续的字符串文字。k2arahey2#
此行为的原因是无符号整数溢出。在C语言中,需要对无符号整数溢出进行回绕(但有符号整数并非如此)。
一切似乎都指向这样一个事实,即您的机器上
unsigned
类型的大小是4个字节,它可以在 Package 之前存储最多2^32 - 1 = 4294967295
的值。您可以使用sizeof(<the_type>)
检查类型的大小(即,在您的情况下为sizeof(unsigned)
)。在您的例子中,
sum
溢出之前i
是92681
,相当于92682 * 92681 / 2 = 4294930221
1的累加和,小于4294967295
。然后添加98682
并得到4294930221 + 98682 = 4295022903
,它无法容纳计算机上的无符号int,因此它会绕回4295022903 % 2^32 = 55607
。将print语句移动到for循环中,以查看其实际效果。您应该会看到类似于
最后,请注意,您得到的结果等于
500050000 % 2^32
。ps.你可能想查找format specifiers进行打印。
1网址:http://en.wikipedia.org/wiki/1_%2B_2_%2B_3_%2B_4_%2B_%E2%8B%AF
um6iljoc3#
正如你所说的“但正确答案应该是5000050000”,但
unsigned int
是4294967295,5000050000 > 4294967295,所以unsigned int
不能容纳结果,你需要使用更大的类型,如unsigned long long
,此类型的最大值为18446744073709551615,大于5000050000,它可以让你得到正确的结果。当你运行以下代码时:
您将看到以下输出,演示使用两种不同int类型的影响。