簡體   English   中英

當 n 非常大時,辛普森的復合規則給出了太大的值

[英]Simpson's Composite Rule giving too large values for when n is very large

使用辛普森的復合規則計算1/ln(x)21,000的積分,但是當使用較大的n (通常約為500,000 )時,我開始得到與我的計算器和其他來源給我的值不同的結果( 176.5644 )。 例如,當n = 10,000,000時,它給我的值為184.1495 想知道為什么會這樣,因為隨着 n 變大,精度應該會增加而不是降低。

#include <iostream>
#include <cmath>

// the function f(x)
float f(float x)
{
    return (float) 1 / std::log(x);
}




float my_simpson(float a, float b, long int n)
{
  if (n % 2 == 1) n += 1; // since n has to be even
  float area, h = (b-a)/n;


  float x, y, z;
  for (int i = 1; i <= n/2; i++)
  {
    x = a + (2*i - 2)*h;
    y = a + (2*i - 1)*h;
    z = a + 2*i*h;
    area += f(x) + 4*f(y) + f(z);
  }

  return area*h/3;
}



int main()
{
    std::cout.precision(20);
    int upperBound = 1'000;
    int subsplits = 1'000'000;

    float approx = my_simpson(2, upperBound, subsplits);

    std::cout << "Output: " << approx << std::endl;

    return 0;
}

更新:從花車切換到雙打,現在效果好多了! 謝謝!

與實數(在數學意義上)不同, float的精度有限。

典型的 IEEE 754 32 位(單精度)浮點數二進制表示僅將 24 位(其中一位是隱含的)用於尾數,並且轉換為大約少於 8 個十進制有效數字(請將此視為粗略)。

另一端的double具有 53 個有效位,使其更准確,並且(通常)是當今數值計算的首選。

因為隨着 n 變大,精度應該增加而不是減少。

不幸的是,它不是這樣工作的。 有一個汗點,但在那之后,舍入誤差的積累盛行,結果與預期值背道而馳。

在 OP 的情況下,這個計算

area += f(x) + 4*f(y) + f(z);

由於area變得遠大於f(x) + 4*f(y) + f(z) (例如 224678.937 與 0.3606823),引入(並累積)舍入誤差。 n越大,相關性越早,從而使結果與真實結果不同。

如評論中所述,另一個問題(未定義的行為)是該area未初始化(為零)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM