[英]Simpson's Composite Rule giving too large values for when n is very large
使用辛普森的復合規則計算1/ln(x)
從2
到1,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.