e^x 的无限和收敛到不正确的值

2024-04-09

我正在尝试实现一种不使用阶乘来计算 e^x 的方法。我通过获取每两个连续项之间的比率来做到这一点,并通过将该比率与上一项相乘来计算下一项。所有这些都会添加到结果总和中,直到该项足够小而无关紧要。

对于较小的 x 值,这是有效的。为了“极端”x 的值,这会由于某种原因而中断。我尝试了 -50,它应该打印 1.9287498e-22 (以固定形式)。 我得到的是 GNU GCC 中的 -56676.4235303065 和 VC++ 中的 2041.8329628977 。两者都大错特错。这是我的代码:

#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;

int main()
{
    double x;
    cout << fixed << setprecision(10) ;
    cout << "Enter x: " << endl;
    cin >> x;
    double sum = 0;
    long long i = 0;
    double term = 1;
    do
    {
        sum += term;
        term *= (x / (++i));
    } while (fabs(term) > 1e-10);
    cout << sum << endl;
}

这是我的问题:导致出现此错误的问题是什么only对于 x 的大值,我该如何修复这个错误?为什么 GNU GCC 和 VC++2017 得到完全不同的答案?


该求和中的最大项比精度高约 10 个数量级double: ~ 2.92e+20相比于double13 平方英尺或者。这些术语中的误差幅度本身比求和结果大约 30 个数量级。

因此,您的级数无法正确收敛也就不足为奇了,因为连续项(相反符号)可能不会按理论量抵消。即使使用一些数值技巧,例如 Kahan-Neumaier 求和以及在相加之前对项进行排序,结果仍然只能简化为~6000。请注意,对于积极的情况,不会发生这种情况x因为连续的任期不需要取消。

克服这个问题的一种方法是对x,并使用乘方求幂来放大到正确的值x.

更新:上述方法的实现:

// integer exponentiation by squaring (won't explain here)
double pow_square(double x, unsigned a)
{
   double r = 1.0;
   while (a > 0)
   {
      if (a % 2 == 1)
      {
         a--;
         r *= x;
      }
      a /= 2;
      x *= x;
   }
   return r;
}

// original method
double exp_original(double x, double e)
{
   double sum = 0.0;
   unsigned i = 0;
   double term = 1.0;
   do
   {
      sum += term;
      term *= (x / (++i));
   } while (fabs(term) > e);
   return sum;
}

// new adaptive method
double exp_new(double x, double e)
{
   static const double min_X = -3;

   // if within limit, simply use original function
   if (x >= min_X)
      return exp_original(x, e);

   // compute smallest possible scaling coefficient
   unsigned s = (unsigned)(x / (-min_X) + 0.5);
   double p = exp_original(x / s, e);
   return pow_square(p, s);
}

测试范围大x值证实了新方法处理极值(negative)情况要好得多:

x    | exp (C-library)    exp_original       exp_new
-------------------------------------------------------------
-10  | 4.53999297625e-05  4.53998989141e-05  4.53999299001e-05
-30  | 9.35762296884e-14  6.10299992426e-06  9.35762292245e-14
-50  | 1.92874984796e-22  2041.8329629       1.92874983803e-22
-60  | 8.7565107627e-27   722745700.93       8.75651067587e-27
-80  | 1.80485138785e-35  2.45082011705e+17  1.80485137011e-35
-100 | 3.72007597602e-44  8.1446527451e+25   3.72007589785e-44
-150 | 7.17509597316e-66  -9.14622659954e+47 7.1750957953e-66
-200 | 1.38389652674e-87  7.69097143891e+69  1.38389648613e-87
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

e^x 的无限和收敛到不正确的值 的相关文章

  • GCC C++ (ARM) 和指向结构体字段的 const 指针

    假设有一个简单的测试代码 typedef struct int first int second int third type t define ADDRESS 0x12345678 define REGISTER type t ADDRE
  • MEX 文件中的断言导致 Matlab 崩溃

    我正在使用mxAssert 宏定义为matrix h在我的 C 代码中 mex 可以完美编译 当我调用的 mex 代码中违反断言时 该断言不会导致我的程序崩溃 而是导致 Matlab 本身崩溃 我错过了什么吗 这是有意的行为吗 当我查看 M
  • 添加对共享类的多个 WCF 服务的服务引用

    我正在尝试将我的 WCF Web 服务拆分为几个服务 而不是一个巨大的服务 但是 Visual Studio Silverlight 客户端 复制了两个服务共享的公共类 这是一个简单的例子来说明我的问题 在此示例中 有两个服务 两者都返回类
  • 获取两个字符串之间的公共部分c# [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我需要的是获取两个单词之间的共同部分并获取差异 例子 场景1 word1 感言 word2 Test 将返回 公共部分Test 不同之
  • try-catch 中未处理的异常

    try list from XElement e in d Descendants wix File where e Attribute Name Value Contains temp Name e Parent Parent Attri
  • 调试内存不足异常

    在修复我制作的小型 ASP NET C Web 应用程序的错误时 我遇到了 OutOfMemoryException 没有关于在哪里查看的提示 因为这是一个编译时错误 如何诊断此异常 我假设这正是内存分析发挥作用的地方 有小费吗 Thank
  • 为什么 BOOST_FOREACH 不完全等同于手工编码的?

    From 增强文档 http www boost org doc libs 1 48 0 doc html foreach html foreach introduction what is literal boost foreach li
  • Xamarin Android:获取内存中的所有进程

    有没有办法读取所有进程 而不仅仅是正在运行的进程 如果我对 Android 的理解正确的话 一次只有一个进程在运行 其他所有进程都被冻结 后台进程被忽略 您可以使用以下代码片段获取当前正在运行的所有 Android 应用程序进程 Activ
  • 两组点之间的最佳匹配

    I ve got two lists of points let s call them L1 P1 x1 y1 Pn xn yn and L2 P 1 x 1 y 1 P n x n y n 我的任务是找到它们点之间的最佳匹配 以最小化它
  • C# 创建数组的数组

    我正在尝试创建一个将使用重复数据的数组数组 如下所示 int list1 new int 4 1 2 3 4 int list2 new int 4 5 6 7 8 int list3 new int 4 1 3 2 1 int list4
  • C# 编译器如何决定发出可重定向的程序集引用?

    NET Compact Framework 引入了可重定向程序集引用 现在用于支持可移植类库 基本上 编译器会发出以下 MSIL assembly extern retargetable mscorlib publickeytoken 7C
  • 用于从字符串安全转换的辅助函数

    回到 VB6 我编写了一些函数 让我在编码时无需关心字符串的 null 和 数字的 null 和 0 等之间的区别 编码时 没有什么比添加特殊情况更能降低我的工作效率了用于处理可能导致一些不相关错误的数据的代码 9999 10000 如果我
  • “MyClass”的类型初始值设定项引发异常

    以下是我的Windows服务代码 当我调试代码时 我收到错误 异常 CSMessageUtility CSDetails 的类型初始值设定项引发异常 using System using System Collections Generic
  • std::bind 重载解析

    下面的代码工作正常 include
  • 在 C 中复制两个相邻字节的最快方法是什么?

    好吧 让我们从最明显的解决方案开始 memcpy Ptr const char a b 2 调用库函数的开销相当大 编译器有时不会优化它 我不会依赖编译器优化 但即使 GCC 很聪明 如果我将程序移植到带有垃圾编译器的更奇特的平台上 我也不
  • UWP 无法在两个应用程序之间创建本地主机连接

    我正在尝试在两个 UWP 应用程序之间设置 TCP 连接 当服务器和客户端在同一个应用程序中运行时 它可以正常工作 但是 当我将服务器部分移动到一个应用程序并将客户端部分移动到另一个应用程序时 ConnectAsync 会引发异常 服务器未
  • C# 搜索目录中包含字符串的所有文件,然后返回该字符串

    使用用户在文本框中输入的内容 我想搜索目录中的哪个文件包含该文本 然后我想解析出信息 但我似乎找不到该字符串或至少返回信息 任何帮助将不胜感激 我当前的代码 private void btnSearchSerial Click object
  • 在基类集合上调用派生方法

    我有一个名为 A 的抽象类 以及实现 A 的其他类 B C D E 我的派生类持有不同类型的值 我还有一个 A 对象的列表 abstract class A class B class A public int val get privat
  • boost::program_options:带有固定和可变标记的参数?

    是否可以在 boost program options 中使用此类参数 program p1 123 p2 234 p3 345 p12 678 即 是否可以使用第一个标记指定参数名称 例如 p 后跟一个数字 是动态的吗 我想避免这种情况
  • 从类模板参数为 asm 生成唯一的字符串文字

    我有一个非常特殊的情况 我需要为类模板中声明的变量生成唯一的汇编程序名称 我需要该名称对于类模板的每个实例都是唯一的 并且我需要将其传递给asm关键字 see here https gcc gnu org onlinedocs gcc 12

随机推荐