为什么C语言中的整数求和不正确?[副本]

xqk2d5yq  于 2023-10-16  发布在  其他
关注(0)|答案(3)|浏览(113)

此问题已在此处有答案

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

szqfcxe2

szqfcxe21#

你的机器上的无符号整数类型几乎肯定是32位的。此类型可以容纳的最大数字是4294967295。预期结果大于此值,因此发生整数溢出。
解决方案是为sum使用更大的数据类型。
如果包含<stdint.h>,则可能希望使用uint64_t,使其具有18446744073709551615的最大潜在值。
正如ikegami所指出的,在打印uint64_t值时,您还需要提供正确的格式说明符。通常情况下,您会使用%llu而不是%lld。为了确保获得正确的说明符(有很多),可以包含<inttypes.h>并使用PRIuN系列宏。它们列在前面链接的页面上。
例如

printf("%" PRIu64 "\n", sum);

如果这对C初学者来说很奇怪,PRIu64预处理器宏会插入字符串文字"llu",编译器会将相邻的字符串文字视为一个连续的字符串文字。

k2arahey

k2arahey2#

此行为的原因是无符号整数溢出。在C语言中,需要对无符号整数溢出进行回绕(但有符号整数并非如此)。
一切似乎都指向这样一个事实,即您的机器上unsigned类型的大小是4个字节,它可以在 Package 之前存储最多2^32 - 1 = 4294967295的值。您可以使用sizeof(<the_type>)检查类型的大小(即,在您的情况下为sizeof(unsigned))。
在您的例子中,sum溢出之前i92681,相当于92682 * 92681 / 2 = 4294930221 1的累加和,小于4294967295。然后添加98682并得到4294930221 + 98682 = 4295022903,它无法容纳计算机上的无符号int,因此它会绕回4295022903 % 2^32 = 55607
将print语句移动到for循环中,以查看其实际效果。您应该会看到类似于

.
.
.
4294559503
4294652181
4294744860
4294837540
4294930221
55607
148290
240974
333659
426345
519032
611720
.
.
.

最后,请注意,您得到的结果等于500050000 % 2^32
ps.你可能想查找format specifiers进行打印。
1网址:http://en.wikipedia.org/wiki/1_%2B_2_%2B_3_%2B_4_%2B_%E2%8B%AF

um6iljoc

um6iljoc3#

正如你所说的“但正确答案应该是5000050000”,但unsigned int是4294967295,5000050000 > 4294967295,所以unsigned int不能容纳结果,你需要使用更大的类型,如unsigned long long,此类型的最大值为18446744073709551615,大于5000050000,它可以让你得到正确的结果。
当你运行以下代码时:

#include <stdio.h>
#include <limits.h>
int main(void)
{
    unsigned int sum = 0;
    printf("unsigned int max value is %u\n", UINT_MAX);

    unsigned long long  LongSum = 0;
    printf("unsigned long long value is %llu\n", ULLONG_MAX);
    for (unsigned i = 1; i <= 100000; i++)
    {
        LongSum += i;
    }
    printf("%llu\n", LongSum);
    return 0;
}

您将看到以下输出,演示使用两种不同int类型的影响。

unsigned int max value is 4294967295
unsigned long long value is 18446744073709551615
5000050000

相关问题