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