jsj*_*jsj 42 c floating-point pow floating-point-precision
这里发生了什么:
#include <stdio.h>
#include <math.h>
int main(void) {
printf("17^12 = %lf\n", pow(17, 12));
printf("17^13 = %lf\n", pow(17, 13));
printf("17^14 = %lf\n", pow(17, 14));
}
Run Code Online (Sandbox Code Playgroud)
我得到这个输出:
17^12 = 582622237229761.000000
17^13 = 9904578032905936.000000
17^14 = 168377826559400928.000000
Run Code Online (Sandbox Code Playgroud)
13和14与wolfram alpa cf 不匹配:
12: 582622237229761.000000
582622237229761
13: 9904578032905936.000000
9904578032905937
14: 168377826559400928.000000
168377826559400929
Run Code Online (Sandbox Code Playgroud)
而且,一些奇怪的部分并没有错 - 一个错了!
如果这是我达到pow()
可以为我做什么的限制,有没有可以计算这个的替代方案?我需要一个可以计算的函数x^y
,其中x^y
始终小于ULLONG_MAX.
小智 65
pow
与double
数字一起使用.这些表示形式s*2 ^ e的数字,其中s是53位整数.因此double
可存储的所有整数低于2 ^ 53,但只有一些以上整数2 ^ 53.特别是,它只能表示偶数> 2 ^ 53,因为对于e> 0,该值始终是2的倍数.
17 ^ 13需要54位来精确表示,因此e设置为1,因此计算值变为偶数.正确的值是奇数,因此它不会令人惊讶.同样,17 ^ 14需要58位来表示.它也是一个一个是幸运的巧合(只要你没有应用太多的数论),它恰好是32的倍数中的一个,这是该double
数量的数量的粒度圆润.
对于精确整数取幂,您应该一直使用整数.编写自己的double
免费取幂程序.如果y
可能很大,则通过平方使用取幂,但我认为它总是小于64,这使得这个问题没有实际意义.
M O*_*ehm 14
你得到的数字太大,无法double
准确表示.双精度浮点数基本上有53个有效二进制数字,可以表示最大为2^53
9,007,199,254,740,992的所有整数.
对于更高的数字,最后的数字会被截断,计算结果将四舍五入到下一个可以表示为a的数字double
.因为17^13
,这仅略高于极限,这是最接近的偶数.对于大2^54
于此数字的数字,可以被4整除的最接近数字,依此类推.
bar*_*nos 14
如果您的输入参数是非负整数,那么您可以实现自己的pow
.
递归:
unsigned long long pow(unsigned long long x,unsigned int y)
{
if (y == 0)
return 1;
if (y == 1)
return x;
return pow(x,y/2)*pow(x,y-y/2);
}
Run Code Online (Sandbox Code Playgroud)
迭代:
unsigned long long pow(unsigned long long x,unsigned int y)
{
unsigned long long res = 1;
while (y--)
res *= x;
return res;
}
Run Code Online (Sandbox Code Playgroud)
有效率的:
unsigned long long pow(unsigned long long x,unsigned int y)
{
unsigned long long res = 1;
while (y > 0)
{
if (y & 1)
res *= x;
y >>= 1;
x *= x;
}
return res;
}
Run Code Online (Sandbox Code Playgroud)