#include <stdio.h>
#include <string.h>
int main() {
int start, end, i, sum = 0, temp, x, y, z;
puts("Please enter the starting number: ");
scanf("%d", &start);
temp = start;
x = start; y = start + 1;
puts("Please enter the last number till you want to add: ");
scanf("%d", &end);
for (i = start; i < end; i++) {
z = x + y;
x = z;
y = y + 1;
}
printf("The sum of the numbers starting from %d to %d is %d", temp, end, z);
}
谁能找出这段代码有什么问题?
对于较少的数字它工作正常,但是当我分配像 1 到 1000000 这样的大数字时,它不起作用,即它返回奇怪的值。
案例 1:
Please enter the starting number:
1
Please enter the last number till you want to add:
100
The sum of the numbers starting from 1 to 100 is 5050
但在这种情况下 -
情况 2:
Please enter the starting number:
1
Please enter the last number till you want to add:
1000000
The sum of the numbers starting from 1 to 1000000 is 1784293664
这种情况有什么问题?提前致谢。
答案 0 :(得分:1)
您使用的 int
分别只有 -32,768 to 32,767
和 -2,147,483,648 to 2,147,483,647
的值范围 2 byte
或 4 byte
。
您应该将 unsigned long long
用于具有值范围 0 to 18,446,744,073,709,551,615
的代码。
答案 1 :(得分:1)
这是一个数据溢出的案例。
对于从 1 到 1000000 的计算示例,从 1 到 x 的连续数字之和为 x(x+1)/2,即 500.000.500.000,该值大大高于 int (2.147. 483 647)。
考虑使用 long long int,并且不要忘记,无论您的变量的字节大小如何,直到某个值,您无论如何都会溢出。
答案 2 :(得分:1)
对于大数,您必须使用 unsigned long long int
而不是 int
。这里的 int
表示最多 3 位或 4 位数字的整数,但是当您输入 5 位或更多位数字时,它会给您带来奇怪的值。
答案 3 :(得分:1)
int
类型的范围不足以表示 start
和 stop
的大值的总和值(例如 0
到 { {1}} 超过 65536
)。变量 2147483647
、x
和 y
应使用类型 z
定义,该类型保证表示最大为 long long
(9.22E18) 或 {{1 }} 到 9223372036854775807
(1.84E19)。
此外,您计算总和的算法是复杂的,具有不必要或未使用的中间变量。简单为王!
这是修改后的版本:
unsigned long
对于正 18446744073709551615
和 #include <stdio.h>
#include <string.h>
int main() {
int start, end, i;
long long sum;
puts("Please enter the starting number: ");
if (scanf("%d", &start) != 1)
return 1;
puts("Please enter the last number till you want to add: ");
if (scanf("%d", &end) != 1)
return 1;
sum = 0;
for (i = start; i <= end; i++) {
sum = sum + i;
}
printf("The sum of the numbers from %d to %d is %lld\n", start, end, sum);
return 0;
}
值,有一个直接的公式来计算结果。您可以用以下表达式替换 start
循环:
stop
简化为:
for
如果 if (start <= stop) {
// take the sum of integers from 0 to stop: stop * (stop + 1) / 2
sum = (long long)stop * (stop + 1) / 2;
// subtract the sum of integers from 0 to start - 1: (start - 1) * start / 2
sum -= (long long)start * (start - 1) / 2;
} else {
sum = 0;
}
和/或 if (start <= stop) {
sum = ((long long)stop + start)(stop - start + 1) / 2;
} else {
sum = 0;
}
可以为负,总和仍然可以直接计算为:
start
简化为:
stop
答案 4 :(得分:1)
求连续数之和的问题
OP 的代码反复添加并尝试大于 INT_MAX
的总和,导致结果不正确。
使用更广泛的类型来计算总和,例如 long long
或 intmax_t
。
性能:不要使用循环。整数 [0...N] 之和为 N*(N+1)/2
相反:
//for (i = start; i < end; i++) {
// z = x + y;
// x = z;
// y = y + 1;
//}
// Sum 0 to start
long long sum_start = ((long long) start + 1) * start / 2; // or (start + 1LL)*start/2;
// Sum 0 to end
long long sum_end = ((long long) end + 1) * end / 2;
// vvvv specifier change
printf("The sum of the numbers starting from %d to %d is %lld",
temp, end, sum_end - (sum_start - start));
答案 5 :(得分:0)
在第二种情况下,您使用的数字大于整数数据类型的允许范围(对于 16 位架构,从 -32768
到 32767
,从 {{1} } 到 -2,147,483,648
对于 32 位架构。)这就是它导致 integer overflow 问题的原因。要解决此问题,您可以使用其他更大的数据类型,例如 2,147,483,647
或 long int
,但我建议您使用它们的未签名数据类型,即 long long int
或 unsigned long int
,如果您是不打算使用负数,因为无符号数据类型的范围从 0 开始。
答案 6 :(得分:0)
抱歉,您不知道以下计算总和的方法吗?
long sum_from_a_to_b(long a, long b)
{
int n;
int acc = 0;
for (n = a; n <= b; n++)
acc += n;
return acc;
}
顺便说一下,有一个更好的公式,它不需要循环:
#include <assert.h>
/* assumed that a <= b */
long sum_from_a_to_b(long a, long b)
{
assert(a <= b);
return b*(b + 1)/2 - a*(a - 1)/2;
}