pow()似乎在这里出了一个

这里发生了什么:

#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)); } 

我得到这个输出:

 17^12 = 582622237229761.000000 17^13 = 9904578032905936.000000 17^14 = 168377826559400928.000000 

13和14不匹配wolfram alpa cf:

 12: 582622237229761.000000 582622237229761 13: 9904578032905936.000000 9904578032905937 14: 168377826559400928.000000 168377826559400929 

而且,一些奇怪的部分并没有错,只有一个是错的!

如果这是我达到pow()可以为我做的极限,是否有一个替代scheme可以计算出来? 我需要一个可以计算x^y的函数,其中x^y总是小于ULLONG_MAX。

pow工作double号。 这些表示formss * 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,这个问题是没有实际意义的。

你得到的数字太大,不能准确地用double来表示。 双精度浮点数基本上有53个重要的二进制数字,可以表示所有的整数,最多2^53或9,007,199,254,740,992。

对于更高的数字,最后的数字会被截断,并且您的计算结果将被舍入到可以用double表示的下一个数字。 对于仅仅略高于极限的17^13 ,这是最接近的偶数。 对于大于2^54的数字,这是可以被四整除的最接近的数字,依此类推。

如果你的input参数是非负整数,那么你可以实现你自己的pow

recursion:

 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,yy/2); } 

迭代:

 unsigned long long pow(unsigned long long x,unsigned int y) { unsigned long long res = 1; while (y--) res *= x; return res; } 

有效率的:

 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; } 

其他好的答案的一个小增加:在x86架构下通常有可用的x87 80位扩展格式 ,大多数C编译器通过long doubletypes支持。 这种格式允许以最大2^64整数进行操作而无间隙。

<math.h>pow()模拟,它是用来处理long double数的 – powl() 。 还应该注意的是, long double值的格式说明符不是double精度值 – %Lf 。 所以使用long doubletypes的正确程序如下所示:

 #include <stdio.h> #include <math.h> int main(void) { printf("17^12 = %Lf\n", powl(17, 12)); printf("17^13 = %Lf\n", powl(17, 13)); printf("17^14 = %Lf\n", powl(17, 14)); } 

正如斯蒂芬·佳能在评论中指出的那样,不能保证这个程序应该给出确切的结果。