【发布时间】:2013-08-20 12:20:37
【问题描述】:
我正在尝试在 C 中进行手动操作(相当于 Math.pow()),所以在这里,它是:41619^6。
float sum = 41619;
float a = sum;
int k;
for (k = 0; k < 5; k++) {
sum = sum * a;
}
printf("%f", sum);
// sum should be 41619 ^ 6 now
但是,我在这里失去了精确度。我收到5196966085285475633789403136,答案应该是5196965646007524312007756281。
我尝试将 sum 更改为 double,但仍然丢失精度。
如何在不使用 Math.pow() 的情况下实现这一点(对于我尝试运行的测试来说太慢了),并且不损失精度?
【问题讨论】:
-
您是否考虑过原因
pow速度慢的可能性是它不会丢失精度? -
话虽如此,没有办法将确切的值存储在
float甚至double中。这些类型根本没有足够的精度来表示它。但是,pow比您的循环做得更好。 -
log_2 5196965646007524312007756281 ≈ 92。这个数量级的大多数整数不能用单精度或双精度浮点数(23 或 52 位尾数)精确表示。也许这个特定的数字恰好是可以概括表示的那些数字之一,但这也不足为奇。
-
@delnan:不,它不是其中之一。对于 2^n, 2^(n+1) 范围内的任何奇数 x,x^k 是奇数(因此仍然需要最低位),并且最高位在 n*k 或更高的位置。除非 n 和 k 都非常小,否则 x^k 不能精确表示。
-
顺便说一句,稍微提高精度和速度的一种方法是将操作重组为
(a*a)*(a*a)*(a*a)。这只需要 3 次乘法而不是 5 次。