C#中PointCollection的数值积分
Posted
技术标签:
【中文标题】C#中PointCollection的数值积分【英文标题】:Numerical Integration of PointCollection in C# 【发布时间】:2021-12-25 21:57:05 【问题描述】:我有一个 PointCollection,其中包含我生成的正弦数据。 现在我必须建立这些数据的数值积分并将其与正弦数据(每折线)一起绘制。 我在***上找到了这个函数,但它并没有真正起作用:( sin(x) 的积分通常应该是 -cos(x),但我得到的是 -sin(x),我必须缩放 ypos,但在类似的插值函数中,它无需缩放即可工作。有人知道我的问题在哪里吗?
红色:原始噪声数据,蓝色:插值数据绿色:综合数据
private PointCollection Numerical_Integration(PointCollection input_data)
PointCollection integrated_data = new();
for (int i = 1; i < input_data.Count; i++)
double integrated_ypos = (input_data[i].Y + input_data[i - 1].Y) / 2 * (input_data[i].X - input_data[i - 1].X);
integrated_data.Add(new Point(input_data[i].X, integrated_ypos/5+300));
return integrated_data;
【问题讨论】:
幻数y/5+300
是什么意思?
这就是缩放,我已经谈过了。而且我不明白,为什么我需要它来适应我的画布。
您的问题是正 y 值指向下方(像素坐标)并且您的输入数据有 y 值指向上方,就像在正常的笛卡尔坐标中一样系统?
这应该不是问题,因为原始数据和插值数据显示正确。并且所有这些函数都得到相同的输入数据,除了积分函数。得到的就是插值数据。
从笛卡尔坐标系到像素坐标系的转换发生在我从 csv 文件中读取数据的函数中。
【参考方案1】:
这使用标准梯形规则进行积分。
程序
static class Program
static void Main(string[] args)
// Integrate f(x) = 10*cos(x) between x=0..4π
var curve = new PointCollection();
const int n = 180;
for (int i = 0; i < n; i++)
float x = (float)( (4 * Math.PI * i) / n );
float y = (float)( 10 * Math.Cos(x) );
curve.Add(new PointF(x, y));
var integral = Integrate(curve, 0f);
// Compare results to 10*sin(x)
float max_error = 0;
for (int i = 0; i < n; i++)
float x = (float)((4 * Math.PI * i) / n);
float iy_expect = (float)(10 * Math.Sin(x));
float iy_actual = integral[i].Y;
float iy_error = Math.Abs(iy_actual - iy_expect);
max_error = Math.Max(max_error, iy_error);
Console.WriteLine($"Steps = n, Max Error = max_error.");
public static PointCollection Integrate(PointCollection inputData, float integrationConstant = 0)
float h;
var integral = new PointCollection();
integral.Add(new PointF(inputData[0].X, integrationConstant));
for (int i = 1; i < inputData.Count; i++)
h = inputData[i].X - inputData[i - 1].X;
float iy = integral[i - 1].Y + h * (inputData[i].Y + inputData[i - 1].Y) / 2;
integral.Add(new PointF(inputData[i].X, iy));
return integral;
输出
Steps = 180, Max Error = 0.004058838.
从输出中可以看出,考虑到输入曲线的分辨率,误差相当不错。
错误分析
考虑到越来越多的步骤,这是我报告的最大错误:
Steps Error
16 0.5194054
32 0.1288424
64 0.03214836
128 0.008034706
256 0.002008438
512 0.0005044937
1024 0.0001296997
2048 3.71933E-05
4096 1.049042E-05
8192 1.716614E-05
16384 1.335144E-05
32768 2.288818E-05
如您所见,我在大约 4096 步处达到了 float
数字的精度极限。
【讨论】:
PointCollection
表示 Point
结构的集合,其 coordinates 是 double
而不是 float
。以上是关于C#中PointCollection的数值积分的主要内容,如果未能解决你的问题,请参考以下文章