【问题标题】:Calculating e^x without using any functions不使用任何函数计算 e^x
【发布时间】:2010-10-24 02:01:48
【问题描述】:

我们应该使用这种公式来计算 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++ 编写的。

【问题讨论】:

  • 为什么不把阶乘变成双倍呢?

标签: c++ math exponential


【解决方案1】:

我可以想到另一种解决方案。 让pow(e,x) = pow(10, m) * b 其中b>=1< 10,然后

m = trunc( x * log10(e) )

其中log10(e) 是一个常数因子。

b = pow(e,x)/pow(10, m ) = pow(e,x)/pow(e,m/log10(e)) = pow (e,x-m/log10(e))

由此你得到:

z = x-m/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。

【讨论】:

  • 当然会更快——写exp(x)会更快——但它不满足“不使用任何函数计算e^x”的要求。 :-)
  • @ShreevatsaR:实际上,我认为确实如此——尽管我看不到以 10 为底的计算有任何优势。该解决方案在哪里使用任何功能
  • @jpalecek:pow() 是一个内置函数,就像 exp()。我假设原始海报的意图正是使用 exp() 或其他此类函数(或者甚至,也许意图是使用给定的系列)。
  • @ShreevatsaR: 你不能在没有实际调用std::pow 的情况下执行pow(10, integer) 吗?这对我来说似乎是一项幼儿园任务......
  • @ShreevatsaR:是的 - 有点。关键是,泰勒级数在零附近收敛得更快(并且均匀地在零附近的任何圆盘上)因此更容易计算(比较你的“最大项”,即第 700 项与此处所述的 37 个项)。
【解决方案2】:

您在这里介绍的是Horner scheme 计算多项式的应用程序。

【讨论】:

    【解决方案3】:

    x^n 和 n!随着 n 快速增长(分别为指数和超指数),并且很快就会溢出您使用的任何数据类型。另一方面,x^n/n!下降(最终),你可以在它很小的时候停下来。也就是说,使用 x^(n+1)/(n+1)! = (x^n/n!) * (x/(n+1))。像这样说:

    term = 1.0;
    for(n=1; term >= 1.0E-10; n++)
    {
        eValue += term;
        term = term * x / n;
    }
    

    (直接在此框中输入代码,但我希望它应该可以工作。)

    编辑:注意术语 x^n/n!是,对于较大的 x,先增加一段时间,然后再减少。对于 x=709,它上升到 ~1e+306,然后下降到 0,这正好处于 double 可以处理的极限(double 的范围是 ~1e308 和 term*x 将其推过),但long double 工作正常。当然,您的最终 result ex 大于任何项,因此假设您使用的数据类型足够大以容纳结果,您将很好。

    (对于 x=709,如果您使用 term = term / n * x,则可以只使用 double,但它不适用于 710。)

    【讨论】:

    • 很抱歉,我无法理解它。当我用 709 替换 X 时,答案是 1.8046..e+016
    • 是的,我在答案中添加了一条注释来解决这个问题。 x=709 处于 double 可以处理的极限。
    • 哦.. 谢谢!!如果不是太多,你能解释一下你刚刚提出的数学吗?不知道一个简单的术语 * x / n 是如何做到的......我最初的解决方案显然比它应该的要长很多
    • 数学不算多 :) 项是 1, x/1, xx/(1*2), xxx/(1 *2*3)、xxxx/(1*2*3*4) 等等。也就是说,x^2/2!项是 (x/2) 乘以 x^1/1!术语,x^3/3!项是 (x/3) 乘以 x^2/2!项等。一般来说,x^n = x^(n-1)*x 和 n!=(n-1)!*n(这是阶乘的定义),所以 x^n/n! = x^(n-1)*x/((n-1)!*n) = [x^(n-1)/(n-1)!] * (x/n)。也就是说,x^n/n! term 是前一个 term 的 x/n 倍。
    • 或者,换一种说法——你的代码有“power = power * input; factorial = factorial * counter; result = power / factorial;”而我的只有“结果=结果*输入/计数器;”。同样的事情。
    【解决方案4】:

    如果将factorial 的类型从long long 更改为double,会发生什么?

    【讨论】:

    • 尝试计算 e^709 并产生 double 类型的阶乘:-1.#IND 我猜最大迭代次数是 172
    猜你喜欢
    • 2021-01-24
    • 2023-03-17
    • 2014-03-27
    • 2021-02-03
    • 2018-02-19
    • 1970-01-01
    • 2014-05-28
    • 1970-01-01
    • 2016-01-24
    相关资源
    最近更新 更多