我用 C 语言编写了一个程序,它接受两个输入,x 和 n,并将 x 提高到 n 次方。 10^10 不起作用,发生了啥?
Posted
技术标签:
【中文标题】我用 C 语言编写了一个程序,它接受两个输入,x 和 n,并将 x 提高到 n 次方。 10^10 不起作用,发生了啥?【英文标题】:I've made a program in C that takes two inputs, x and n, and raises x to the power of n. 10^10 doesn't work, what happened?我用 C 语言编写了一个程序,它接受两个输入,x 和 n,并将 x 提高到 n 次方。 10^10 不起作用,发生了什么? 【发布时间】:2020-06-24 00:03:42 【问题描述】:我用 C 语言编写了一个程序,它接受两个输入,x 和 n,并将 x 提高到 n 次方。 10^10 不行,怎么回事?
#include <cs50.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
float isEven(int n)
return n % 2 == 0;
float isOdd(int n)
return !isEven(n);
float power(int x, int n)
// base case
if (n == 0)
return 1;
// recursive case: n is negative
else if (n < 0)
return (1 / power(x, -n));
// recursive case: n is odd
else if (isOdd(n))
return x * power(x, n-1);
// recursive case: n is positive and even
else if (isEven(n))
int y = power(x, n/2);
return y * y;
return true;
int displayPower(int x, int n)
printf("%d to the %d is %f", x, n, power(x, n));
return true;
int main(void)
int x = 0;
printf("What will be the base number?");
scanf("%d", &x);
int n = 0;
printf("What will be the exponent?");
scanf("%d", &n);
displayPower(x, n);
例如,这里有一对有效的输入:
./exponentRecursion
What will be the base number?10
What will be the exponent?9
10 to the 9 is 1000000000.000000
但这就是我用 10^10 得到的:
./exponentRecursion
What will be the base number?10
What will be the exponent?10
10 to the 10 is 1410065408.000000
为什么会写出这么奇怪的数字?
顺便说一句,10^11 返回 14100654080.000000,正好是上面的十倍。
也许我使用的数据类型有一些“限制”?我不确定。
【问题讨论】:
您正在以奇怪且不那么奇妙的方式混合float
s 和int
s。您首先需要确定是在计算 float
还是和 int
,然后在所有计算中始终使用正确的类型。
int y = power(x, n/2);
这会将浮点数转换为整数。然后你 return y * y;
这是一个整数乘法。但整数乘法不能高达 10^10。它的最大值约为 2 * 10^9。
不可能!?所以有一个限度。正如 dbush 建议的那样,双打会更好。
【参考方案1】:
您的变量 x 是 int
类型。最常见的内部表示是 32 位。这是一个有符号二进制数,因此只有 31 位可用于表示幅度,通常的最大正 int 值为 2^31 - 1 = 2,147,483,647。任何更大的都会溢出,给出更小的量级并且可能是负号。
对于更大的范围,您可以将 x 的类型更改为 long long
(通常为 64 位 - 约 18 位)或double
(通常为 64 位,51 位精度约 15 位)。
(警告:许多实现对int
和long
使用相同的表示,因此使用long
可能不会有所改进。)
【讨论】:
【参考方案2】:float
仅对大约 7 位十进制数字具有足够的精度。任何位数多于该数字的数字都只是一个近似值。
如果您切换到double
,您将获得大约 16 位的精度。
【讨论】:
【参考方案3】:当您开始使用 C 中的 基本 数据类型处理大数时,您可能会遇到麻烦。
整数类型的值范围有限(例如 32 位无符号整数的 4x109)。浮点类型具有更大的范围(尽管不是无限的)但精度有限。例如,IEEE754 双精度可以在 +/-10308
范围内为您提供大约 16 个十进制数字的精度要恢复这两个方面,您需要使用某种 bignum 库,例如 MPIR。
【讨论】:
【参考方案4】:如果您在 C 程序中混合不同的数据类型,编译器会执行几种隐式转换。由于编译器的工作方式有严格的规则,因此您可以准确地弄清楚您的程序会发生什么以及为什么。
由于我不知道所有这些强制转换规则,我做了以下事情:估计最大结果所需的最大精度。然后将过程中的每个变量和函数显式转换为这个精度,即使没有必要。通常这会像解决方法一样工作。
【讨论】:
以上是关于我用 C 语言编写了一个程序,它接受两个输入,x 和 n,并将 x 提高到 n 次方。 10^10 不起作用,发生了啥?的主要内容,如果未能解决你的问题,请参考以下文章