使用最大有符号 int 值时,项目 euler 的函数出错

Error in function from project euler when using largest signed int value

我为了好玩而做欧拉问题,决定看看我的计算机能多快解决这个最大有符号整数的问题:https://projecteuler.net/problem=1

不幸的是,当我尝试使用最大的有符号整数值 2147483647 时,我得到了一个负值(溢出?),如您在这张图片中所见:

为什么我在使用 2147483647-1 时得到看似正确的答案,但在使用 2147483647 时却得到错误的值?

这是我的代码

#include <stdio.h>
int getsums(int v) {
    int sum, i; sum = i = 0;
    for(;i<v; i++){
        if ( i%3 == 0 || i%5 == 0 ){
            sum +=i;
        }
    }
    return sum;
}

int main(void) {
    int upperlimit = 0;
    int sums = 0;

    printf("Intervalo de 0 a (escreva um numero)\n");
    printf(">>");

    scanf("%d", &upperlimit);
    sums = getsums(upperlimit);

    printf("somas dos multiplos de 3 e 5 no intervalo [0;%d] e: %d\n", upperlimit, sums);

    return 0;
}

结果太大,无法放入 int 类型,您应该使用 unsigned 类型,因为不可能出现负结果,同时将格式说明符更改为 %u对于 printf:

unsigned int getsums(int v) {
    unsigned int sum = 0;
    int i = 0;
    for(;i<v; i++){
        if (i%3 == 0 || i%5 == 0 ){
            sum +=i;
        }
    }
    return sum;
}

int main(void) {
    int upperlimit = 0;
    unsigned int sums = 0;

    printf("Intervalo de 0 a (escreva um numero)\n");
    printf(">>");

    scanf("%d", &upperlimit);
    sums = getsums(upperlimit);

    printf("somas dos multiplos de 3 e 5 no intervalo [0;%d] e: %u\n", upperlimit, sums);

    return 0;
}

intunsigned 不足以存储高输入的结果。你在另一种情况下得到的那个正数也是不正确的。要查看,请考虑 INT_MAX - 3(这个或它上面的三个数字必须能被 3 整除)。如果你把前两个数从 INT_MAX - 3 加到 0,这意味着你肯定已经溢出 INT_MAX,因为第二个数肯定是 > 3.

使用 unsigned 在这里无济于事,它只会帮助移动时间,直到发生溢出。 UINT_MAX 大约是 INT_MAX 的两倍,所以你在添加前三个数字时会溢出它,因为 INT_MAX - 3 + INT_MAX - 6 会达到大约 UINT_MAX - 9。现在加上INT_MAX - 9肯定会溢出UINT_MAX - 9因为INT_MAX - 9肯定是> 9.

而是使用 uint64_t。从12^31-1所有个数相加(即n*(n+1)/2)不会超过2^63,所以你肯定是在安全方面有 64 位。

主要问题是 int 不够大,无法容纳 sum

建议以下代码:

#include <stdio.h>

size_t getsums(size_t v)
{
    size_t sum = 0;

    for(size_t i=0; i<v; i++)
    {
        if ( i%3 == 0 || i%5 == 0 )
        {
            sum +=i;
        }
    }
    return sum;
}


int main(void)
{
    size_t upperlimit = 0;
    size_t sums = 0;

    printf("Intervalo de 0 a (escreva um numero)\n");
    printf(">>");

    scanf("%lu", &upperlimit);
    sums = getsums(upperlimit);

    printf("somas dos multiplos de 3 e 5 no intervalo [0;%lu] e: %lu\n", upperlimit, sums);

    return 0;
}

产生以下结果:

Intervalo de 0 a (escreva um numero)
>>2147483647
somas dos multiplos de 3 e 5 no intervalo [0;2147483647] e: 1076060070465310994

以及以下内容:

Intervalo de 0 a (escreva um numero)
>>2147483646
somas dos multiplos de 3 e 5 no intervalo [0;2147483646] e: 1076060068317827348