我正在尝试计算log a b(并获得一个浮点,而不是一个整数)。我计划将此作为log(b)/log(a)
。从数学上讲,我可以使用任何cmath
对数函数(基数2,e或10)来进行计算;但是,我会在我的程序中运行这个计算很多,所以我想知道其中一个是否比其他程序快得多(或者更好的是,如果有更快,但仍然很简单的方法)。如果重要,a和b都是整数。
答案 0 :(得分:15)
首先,预先计算1.0/log(a)
并将每个log(b)
乘以该表达式。
编辑:我原先说自然对数(基数e)会最快,但其他人说基数2直接由处理器支持并且速度最快。我没有理由怀疑它。
编辑2:我原先认为a
是一个常数,但重新阅读了从未说过的问题。如果是这样,那么预先计算将没有任何好处。但是,如果是这样,您可以通过适当选择变量名来保持可读性:
const double base_a = 1.0 / log(a);
for (int b = 0; b < bazillions; ++b)
double result = log(b) * base_a;
奇怪的是,微软没有提供基本2日志功能,这解释了为什么我不熟悉它。此外x86 instruction for calculating logs自动包含乘法,不同基数所需的常数也可以通过optimized instruction获得,所以我希望3个不同的日志函数具有相同的时序(即使是2的基数也是如此)必须乘以1)。
答案 1 :(得分:11)
由于b
和a
是整数,因此您可以使用bit twiddling的所有荣耀来查找基数2的日志。以下是一些:
我会留给您选择最适合您需求的“快速日志”功能。
答案 2 :(得分:4)
在我拥有数据的平台上,log2
比其他平台快一点,符合我的期望。但请注意,差异极轻微(仅百分之几)。这真的不值得担心。
编写一个清晰的实现。然后测量性能。
答案 3 :(得分:1)
在8087指令集中,只有对数为2的对数指令,所以我猜这个指令是最快的。
当然,这类问题在很大程度上取决于您的处理器/架构,因此我建议您进行简单的测试并计算时间。
答案 4 :(得分:0)
答案是:
您甚至没有提到您的CPU类型,变量类型,编译器标志,数据布局。如果您需要并行完成这些操作,我相信会有SIMD选项。只要您使用对齐并清除简单循环(或者如果您喜欢古老的方法则为valarray),您的编译器将优化它。
很可能,英特尔编译器在这方面对英特尔处理器有特定的技巧。
如果你真的想要你可以使用CUDA并利用GPU。
我想,如果你不幸缺少这些指令集you could go down at the bit fiddling level并编写一个does a nice approximation的算法。在这种情况下,我可以打赌不止一个苹果派,2-log将比任何其他基本日志更快