使用最大有符号 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;
}
int
和 unsigned
不足以存储高输入的结果。你在另一种情况下得到的那个正数也是不正确的。要查看,请考虑 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
。从1
到2^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
我为了好玩而做欧拉问题,决定看看我的计算机能多快解决这个最大有符号整数的问题: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;
}
int
和 unsigned
不足以存储高输入的结果。你在另一种情况下得到的那个正数也是不正确的。要查看,请考虑 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
。从1
到2^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