2 ** x的计算速度比exp(x)快吗?


12

原谅我提出这个问题的方式以及我提出的事实中显而易见的天真。

数学家通常使用因为它是理论上最简单/最简单的基础(由于微积分)。但是计算机似乎以二进制形式完成所有工作,因此在计算机上进行计算的速度是否比?exp2**xMath::exp(x)


7
你在说什么电话 任意大小的整数?固定大小的浮点数?任意精度的浮点数?
吉尔斯(Gillles)“所以-别再邪恶了”

@吉尔斯这是一个好点。我没有意识到区别很重要。
同构

3
我已经在一些Casio袖珍计算器上看到,非e数的对数和幂比ln / exp慢得多
phuclv 2014年

2
为了冒险,请问您是否尝试过同时对它们进行计时,看看哪个更快?还是从复杂度的角度讲速度?O(f(n))
jmite 2014年

1
该语言负责选择最快的方式,并将在此方面做得很好。只有在需要最大速度的情况下,并且测量表明该性能与性能相关,您才需要担心这种情况
vonbrand 2014年

Answers:


18

因为这是CS,而不是Stackoverflow,所以我假设您要问一个关于数值分析的问题,(为了简化起见)特别是IEEE-754浮点数。在这种情况下,问题的答案部分取决于您“更轻松”的含义,部分取决于系统的细节。

我所知的现代CPU都没有内置可以完全满足操作(此后我们将其称为C的常规名称)或()的指令的指令。它们都使用库函数来实现。2 Xexexp2xexp2

与用于先验运算的所有数值方法一样,有一些特殊情况需要考虑:

exp(NaN) = NaN
exp(+Inf) = +Inf
exp(-Inf) = 0

但是,还有另一件事使问题稍微复杂一些:有用的域很小。对于binary32,exp(x)如果左右,则下溢;如果左右,则上溢。不寻常的超越行动,我们也可以忽略低于正常情况下,由于是从没有区别,如果是低于正常。上面的所有情况也适用于,除了域略有不同。x > 88.7x<104x>88.7exp(x)1.0xexp2

您的直觉是正确的,因为大多数实现都可以计算。但是,与其余计算相比,通过乘法运算的成本微不足道。典型的方法使用带有元素的预计算表:1ex=2x/ln2 K1ln2exp2K

exp2(x)=2n×T[j]×P(y)

其中是的整数部分,表包含范围内的所有值,是多项式近似值(对于32 )在。在部分是便宜的,因为它只是操纵指数。是一个查询表。因此,可能是操作的昂贵部分。X Ť 2 Ĵ / ķ Ĵ [ 0 ķ P 2 X [ 0 1nxT2j/Kj[0,K)P2x2nTP[0,1K)2nTP

为了完整性,我应该指出英特尔x86 FPU包含一条称为的指令f2xm1,该指令为范围内的计算。但是,在现代CPU上,这是一条相当昂贵且非流水线的指令,因此强烈建议您不要使用它。正如《英特尔优化参考手册》第3.8.5节正确指出的那样:X [ - 1 1 ]2x1x[1,1]

尽管x87支持先验指令,但在许多情况下,先验功能的软件库实现可以更快。

编辑:在评论中已指出,我应该解释IEEE 754-2008中使用的一些新术语。自1985年和1987年以来,某些语言已经发生了变化,并且大多数人对旧术语更加熟悉。

术语“ binary32”和“ binary64”是32位和64位二进制浮点数的新名称,旧标准分别将其称为“单”和“双”。

术语“非正规数”代替了先前的术语“非正规数”或“非正规数”


当您说“次普通”时,您显然不是在说“次高斯”;您的意思是“比[典型性基准]更差”吗?
同构

2
@isomorphismes在这里,“次正规”是关于如何实现浮点数的。请参阅Wikipedia上的异常数
Paul Manta 2014年

顺便说一句,我确实稍微简化了“典型方法”。可以使用这里介绍的方法的一个小扩展(并且很容易理解)以ulp精度实现exp2()和exp(),但是对小易懂的扩展的解释可能会使长度加倍。答案!
别名

6

如果2**x您的意思是,那么可以。我们可以使用左移运算符,即我们进行计算。这是闪电般的速度,因为它是我所知道的每个处理器中的原始机器指令。使用2以外的任何基数都无法做到这一点。此外,整数乘幂总是比实数幂快,因为浮点数的乘积需要更长的时间。2x<<1 << x


4
实际上不是。x可能是浮点类型
phuclv

1
x

如果x不是整数(例如20.75),则应将尾数设置为2,将指数设置为的舍入值x作为最精确的估计值(无法精确表示)。这也比“ pow”快得多。
戴蒙2014年

1

如果2**x是整数函数,那么我同意斯蒂芬的回答,移位比较便宜。但是我通常将2^x**表示为浮点指数。对于这种情况,我希望之间相似的性能**,并^因为这两个exppow(对于底层的操作**)都超越逼近操作。


有趣的是,我不知道这**被认为是浮点版本的同义词(而且,愚蠢的我,我忘记了两者会有所不同)。
同构2014年

1

由于2 ^ x = e ^(x * ln 2)和e ^ x = 2 ^(x * log2(e)),所以您不会期望有太大差异。

对于x接近零的情况,通常会使用多项式e ^ x = 1 + x + x ^ 2/2 + x ^ 3/6 ... 。显然,2 ^ x的计算速度很小。“ x接近0”通常是x的值,其中sqrt(1/2)<= e ^ x <= sqrt(2)。限制x的范围可确保不必将多项式选择得太高。

对于更大的x,通常可以通过让x = x'+ x''来计算2 ^ x,其中x'是整数,-0.5 <= x''<= 0.5。然后,通过使用正确的位模式构造浮点数来计算2 ^ x',对于小x使用e ^ x方法来构造2 ^ x''。在这里,2 ^ x快一点。此外,如果x较大(例如x = 100.3),则仅将x乘以log2(e)会引入不可接受的舍入误差(因为小数位少很多),因此需要格外小心。

并希望有一个好的库函数会注意,无论什么舍入误差,只要x <= y,e ^ x <= e ^ y和2 ^ x <= 2 ^ y。实现这种事情可能很棘手。


0

您必须了解计算机上的数学运算是由不同的软件以不同的方式完成的,希望能给出一致的答案。查看大多数软件,我认为计算机的运行情况良好-计算机,即使是0 ^ 0,也可以很长的时间计算出答案。问题在于特殊情况涉及“识别”,这在数字计算机中不是免费发生的。这意味着,只有在拥有答案的情况下才能“最快速”地进行优化,才会发生优化。但是在那种情况下,它将发生得非常好。还要注意,可能必须进行几种不同的识别才能获得正确的答案。这被称为速度优化级别,这在大多数称为GNU“ C”的软件的基础上已达到最大程度的专业化。这是因为此处使用的是软件之间,软件之间以及计算机之间的运行时间的微小差异作为质量验收指标。在其他解释器中,通常仅当“零标志”出现时,因为先前计算的副作用将加快识别的速度。例如0 * x => C0。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.