不使用任何函数计算 e^x
我们应该使用这种公式来计算 e^x:
e^x = 1 + (x ^ 1 / 1!) + (x ^ 2 / 2!) ......
到目前为止我有这个代码:
while (result >= 1.0E-20 )
{
power = power * input;
factorial = factorial * counter;
result = power / factorial;
eValue += result;
counter++;
iterations++;
}
我现在的问题是,由于阶乘的类型是 long long,所以我无法真正存储大于 20 的数字! 所以发生的情况是,程序在到达该点时输出有趣的数字。
正确的解决方案的 X 值最多为 709,因此 e^709 应该输出:8.21840746155e+307
该程序是用 C++ 编写的。
We are supposed to calculate e^x using this kind of formula:
e^x = 1 + (x ^ 1 / 1!) + (x ^ 2 / 2!) ......
I have this code so far:
while (result >= 1.0E-20 )
{
power = power * input;
factorial = factorial * counter;
result = power / factorial;
eValue += result;
counter++;
iterations++;
}
My problem now is that since factorial is of type long long, I can't really store a number greater than 20! so what happens is that the program outputs funny numbers when it reaches that point ..
The correct solution can have an X value of at most 709 so e^709 should output: 8.21840746155e+307
The program is written in C++.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
x^n 和 n! 随着 n 快速变大(分别为指数和超指数),并且很快就会溢出您使用的任何数据类型。 另一方面,x^n/n! 下降(最终),当它很小时你可以停下来。 也就是说,使用 x^(n+1)/(n+1)! = (x^n/n!) * (x/(n+1))。 像这样,说:(
代码直接输入此框中,但我希望它应该起作用。)
编辑:请注意术语 x^n/n! 是,对于较大的x,增加一段时间然后减少。 对于 x=709,它在减小到 0 之前会上升到 ~1e+306,这正好达到了
double
可以处理的极限(double
的范围是 ~ 1e308 和 term*x 将其推倒),但 long double 工作正常。 当然,您的最终结果 ex 比任何项都大,因此假设您使用的数据类型足够大以容纳结果,您将美好的。(对于 x=709,如果使用
term = term / n * x
,则可以只使用double
,但它不适用于 710。)Both x^n and n! quickly grow large with n (exponentially and superexponentially respectively) and will soon overflow any data type you use. On the other hand, x^n/n! goes down (eventually) and you can stop when it's small. That is, use the fact that x^(n+1)/(n+1)! = (x^n/n!) * (x/(n+1)). Like this, say:
(Code typed directly into this box, but I expect it should work.)
Edit: Note that the term x^n/n! is, for large x, increasing for a while and then decreasing. For x=709, it goes up to ~1e+306 before decreasing to 0, which is just at the limits of what
double
can handle (double
's range is ~1e308 andterm*x
pushes it over), butlong double
works fine. Of course, your final result ex is larger than any of the terms, so assuming you're using a data type big enough to accommodate the result, you'll be fine.(For x=709, you can get away with using just
double
if you useterm = term / n * x
, but it doesn't work for 710.)如果将
factorial
的类型从long long
更改为double
会发生什么?What happens if you change the type of
factorial
fromlong long
todouble
?我可以想到另一个解决方案。
令
pow(e,x) = pow(10, m) * b
其中b
为>=1
且< 10
,那么其中
log10(e)
是一个常数因子。这样
你就得到:
它将在 0 到 3 之间,然后使用 SreevartsR 给出的
b = pow(e,z)
。最终答案是
b 是基数(有效数字),m 是尾数(数量级)。
这将比 SreevartsR 方法更快,并且您可能不需要使用高精度。
祝你好运。
这甚至适用于 x 小于 0 且负值更大的情况,在这种情况下 z 将在 0 到 -3 之间,并且这将比任何其他方法更快。
由于 z 为 -3 到 3,并且如果您需要前 20 个有效数字,则 pow(e,z) 表达式自 3^37/37 起最多只能计算 37 个项! =~3.2e-26。
I can think of another solution.
Let
pow(e,x) = pow(10, m) * b
whereb
is>=1
and< 10
, thenwhere in
log10(e)
is a constant factor.and
By this you get:
which will be in between 0 to 3 and then use
b = pow(e,z)
as given by SreevartsR.and final answer is
b is base(significant digit) and m is mantissa (order of magnitude).
this will be faster than SreevartsR approach and you might not need to use high precisions.
Best of luck.
This will even work for when x is less than 0 and a bigger negative, in that case z will be in between 0 to -3 and this will be faster than any other approach.
Since z is -3 to 3, and if you require first 20 significant digits, then pow(e,z) expression can be evaluated upto 37 terms only since 3^37/37! = ~ 3.2e-26.
您在这里展示的是 Horner 方案 计算多项式的应用程序。
What you presented here is an application of Horner scheme to calculate polynomials.