我想计算 10 的负次幂m
。除了使用数学函数之外pow(10, -m)
,还有什么快速有效的方法吗?
我从 SO 向 c++ 大师提出的一个简单问题是,如您所知,就像基数 2 一样,10 也是一个特殊的基数。如果某个值n
乘以 10 的幂减去m
,则相当于将 n 的小数点向左移动 m 次。我认为这一定是一种快速有效的应对方式。
对于浮点m,只要你的标准库实现写得好,那么pow
就会很高效。
如果 m 是整数,并且您暗示它是整数,那么您可以使用预先计算的值的数组。
如果该例程是您代码中的瓶颈,您应该只担心这种事情。也就是说,如果对该例程的调用占用了总运行时间的很大一部分。
十不是二进制机器上的特殊值,只有二是。通过平方使用pow
或取幂。
不幸的是,没有快速有效的方法来使用 IEEE 754 浮点表示来计算它。m
获得结果的最快方法是为您关心的每个值构建一个表,然后执行查找。
使用查找表不能超过 1000 个浮点数,特别是如果 m 是整数。
IEEE 754 指定了一堆浮点格式。那些被广泛使用的是二进制的,这意味着以 10 为底并没有任何特殊之处。这与您“10 也是一个特殊基数”的假设相反。
有趣的是,IEEE 754-2008 确实添加了十进制浮点格式(decimal32
和朋友)。但是,我还没有遇到这些硬件实现。
无论如何,在分析代码并确定这确实是瓶颈之前,您不应该对代码进行微优化。
只是更多的想法可能会引导您找到进一步的解决方案......
如果您对算法级别的优化感兴趣,您可能会寻找一种并行化的方法。
您可以在使用 Ipp(用于 Intel 处理器)或例如用于 AMD 的 AMD Core Math Library (ACML) 时加快系统/架构级别
使用显卡的力量可能是另一种方式(例如 CUDA 用于 NVIDEA 卡)
我觉得 OpenCL 也值得一看
如果有一种快速有效的方法,那么我相信你的 CPU 支持它,除非你在嵌入式系统上运行,在这种情况下,我希望pow(...) 实现写得很好。
10 对我们来说很特别,因为我们大多数人都有十根手指。计算机只有两位数,所以 2 对它们来说是特殊的。:)
如果您可以长时间使用 log n 而不是 n,您可以节省时间,因为
n = pow(10*n,-m)
您现在必须计算(使用定义 l = log10(n))
l = -m*(l+1)