繁体   English   中英

计算 e^x 的最快方法?

[英]Fastest way to compute e^x?

如果 x 可以是浮点值,计算 e^x 的最快方法是什么。

现在我已经使用 python 的数学库来计算这个,下面是完整的代码,其中result = -0.490631 + 0.774275 * math.exp(0.474907 * sum)是主要逻辑,rest 是问题要求的文件处理代码。

import math
import sys

def sum_digits(n):
   r = 0
   while n:
       r, n = r + n % 10, n // 10
   return r

def _print(string):
    fo = open("output.txt", "w+")
    fo.write(string)
    fo.close()

try:
    f = open('input.txt')
except IOError:
    _print("error")
    sys.exit()
data = f.read()
num = data.split('\n', 1)[0]
try:
   val = int(num)
except ValueError:
    _print("error")
    sys.exit()

sum = sum_digits(int(num))
f.close()

if (sum == 2):
    _print("1")
else:
    result = -0.490631 + 0.774275 * math.exp(0.474907 * sum)
    _print(str(math.ceil(result)))

result的右值是我使用自己的数据集从wolfarm-mathematica导出的曲线方程(这是编程问题的解决方案)。

但这似乎没有通过评估的标准!

我也尝试过 newton-raphson 方法,但较大 x 的收敛导致了问题,除此之外,计算自然对数ln(x)又是一个挑战!

我没有任何语言限制,所以任何解决方案都是可以接受的。 另外,如果 python 的数学库像某些评论所说的那样最快,那么任何人都可以深入了解该程序的时间复杂度和执行时间,简而言之就是程序的效率吗?

我不知道这段代码中的指数曲线数学是否正确,但这当然不是慢点。

首先,您在一个read调用中读取输入数据。 它必须被读取,但是会加载整个文件。 下一步仅采用第一行,因此使用readline似乎更合适。 该拆分本身为O(n),其中n至少是文件大小,它可能包含您忽略的数据,因为您只处理一行。

其次,将那条线转换为int 这可能需要Python的长整数支持,但是操作可以是O(n)或O(n ^ 2)。 单次通过算法会将每个数字的累加数字乘以10,每次分配一个或两个新的(较长)long。

第三, sum_digits将长整数再次分解为数字。 它使用昂贵的除法和两个操作来实现,而不是使用divmod 那是O(n ^ 2),因为每个除法必须处理每个数字的每个更高的数字。 只是因为您刚刚进行了转换,才需要它。

用类似sum(int(c) for c in l if c.isdigit())来对字符串中找到的数字求和可能更容易,其中l是输入行。 这不是特别快,因为数字转换会产生很多开销,并且总和可能会增加,但是它确实通过了一个相当紧密的循环就通过了; 根据数据的长度,它介于O(n)和O(n log n)之间,因为总和本身可能会变大。

至于未知的指数曲线,涉及到一个小数的例外情况的存在。 如果答案始终是整数,则可能还有其他一些选项会更快,更准确。

最后,您至少有四种不同的输出数据格式:error,2、3.0、3e + 20。 您知道这是预期的吗? 也许您应该使用格式化输出而不是str来转换数字。

需要特别注意的是:如果数据确实很大,则分块处理肯定会加快处理速度(而不是耗尽内存,需要交换等)。 当您寻找数字总和时,您的大小复杂度可以从O(n)降低到O(log n)。

e ^ x可以写成1 + x / 1! + x ^ 2/2! + x ^ 3/3! + ......(由Taylor的Expansion撰写),它收敛得非常快。 现在可以将其重写为e ^ x = 1 +(x / 1)(1 +(x / 2)(1 +(x / 3)(........)))来实现这个,我们可以用下面的代码(C代码)

float exp1(int n, float x)
 {   int i;
    float sum = 1.0f; 
     for (i = n - 1; i > 0; --i )
     {
      sum = 1 + x * sum / i;
     }
    return sum;
 }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM