计算e ^ x的最快方法是什么?

时间:2017-06-07 10:35:29

标签: python optimization mathematical-optimization

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

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

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的数学库是最快的,因为有些评论说,那么任何人都可以深入了解该程序的时间复杂度和执行时间,简而言之就是程序的效率吗?

2 个答案:

答案 0 :(得分:1)

我不知道这段代码中的指数曲线数学是否准确,但它肯定不是慢点。

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

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

第三,sum_digits再次将长整数分解为数字。它使用分区,这是昂贵的,也是两个操作,而不是使用divmod。这是O(n ^ 2),因为每个部门必须处理每个数字的每个更高的数字。而且只是因为您刚刚进行的转换才需要它。

使用sum(int(c) for c in l if c.isdigit())之类的内容可以更轻松地对字符串中找到的数字求和,其中l是输入行。它并不是特别快,因为在数字转换中有相当多的开销,并且总和可能会变得很大,但它确实通过相当紧密的循环进行单次传递;它取决于数据的长度,介于O(n)和O(n log n)之间,因为总和本身可能会变大。

对于未知指数曲线,存在低数的异常。如果答案是一个整数,那么其他一些选项可能会更快更准确。

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

一个额外的注意事项:如果数据非常大,那么以块为单位处理它肯定会加快速度(而不是耗尽内存,需要交换等)。当您查找数字总和时,您的大小复杂度可以从O(n)减少到O(log n)。

答案 1 :(得分:-2)

e ^ x可以写成  1 + x / 1! + x ^ 2/2! + x ^ 3/3! + ......(由泰勒的扩张) 它收敛得非常快。 现在这可以重新编写为 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;
 }