[英]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.