我是C语言的新手,正在尝试编写一个计算2 ^ n位数之和的程序,其中 n <10 ^ 8。
例如,对于2 ^ 10,我们将有1 + 0 + 2 + 4,即7。
这是我想出的:
#include <stdio.h>
#include <math.h>
int main()
{
int n, t, sum = 0, remainder;
printf("Enter an integer\n");
scanf("%d", &n);
t = pow(2, n);
while (t != 0)
{
remainder = t % 10;
sum = sum + remainder;
t = t / 10;
}
printf("Sum of digits of 2 to the power of %d = %d\n", n, sum);
return 0;
}
问题是:该程序在小于30的数字下正常运行。将n设置为大于30的数字后,结果始终为 -47 。
我真的不理解此错误以及导致此错误的原因。
答案 0 :(得分:3)
可以肯定,这是一个有趣的问题,但是如果您希望支持大的 n 值,例如10 8 <,我认为解决方案超出了简单答案的范围。 / sup>您提到过。数字2 10 8 需要10 8 + 1(100,000,001)位,即大约12 MB的内存,以二进制形式存储 。用十进制表示,大约有3000万个数字。
您的int
的宽度为32位,这就是为什么有符号的int
不能存储2 31 的原因–第32位是2 31时的符号的二进制数为1,后跟31个零,需要32个无符号的位。因此它溢出并被解释为负数。 (技术上签名的整数溢出是C中未定义的行为。)
您可以切换到unsigned int
来消除符号和不确定的行为,在这种情况下,您支持的新最高 n 将为31。您几乎可以肯定拥有64位可用的整数,甚至可能是128位,但2 127 仍然比2 100000000 小。
所以您要么需要找到一种算法来计算2的幂的小数位数而不实际存储它们(并且仅存储和),要么忘记尝试在标准C中使用任何标量类型并获取(或实现) )在数组(位,十进制数字或二进制编码的十进制数字)上运行的任意精度数学库。另外,您可以将解决方案限制为uint64_t
,但是您有 n <64,这几乎没有意思……=)
答案 1 :(得分:1)
对于signed int t = pow(2,n)
,如果为n >= 31
,则为t > INT_MAX
。
您可以改用unsigned long long t = pow(2,n)
。
这将使您的排名上升到n == 63
。
此外,由于您使用的是基本2
,因此可以使用(unsigned long long)1 << n
代替pow(2,n)
。