C# 求C中正弦/余弦曲线最小值和最大值的最有效方法#

C# 求C中正弦/余弦曲线最小值和最大值的最有效方法#,c#,algorithm,math,curve,numerical-analysis,C#,Algorithm,Math,Curve,Numerical Analysis,背景:我的程序中有一个函数,它获取一组点,并在这些点生成的曲线上找到最小值和最大值。问题是它的速度非常慢,因为它使用while循环根据近似误差计算出最小/最大值。我不完全确定这是什么形式的方法,因为我不是自己写的,但我知道我们需要一个新的更有效的方法 问题:我的问题是,使用C#寻找曲线上的最小-最大点的最佳和最有效的方法/算法是什么,这也是非常精确的 关于曲线:我附近有一本大学的数值分析书,所以我只需要一个方法名和一个正确方向的轻推。我可以生成任意数量的点来近似曲线,但我希望将点的数量保持在一个

背景:我的程序中有一个函数,它获取一组点,并在这些点生成的曲线上找到最小值和最大值。问题是它的速度非常慢,因为它使用while循环根据近似误差计算出最小/最大值。我不完全确定这是什么形式的方法,因为我不是自己写的,但我知道我们需要一个新的更有效的方法

问题:我的问题是,使用C#寻找曲线上的最小-最大点的最佳和最有效的方法/算法是什么,这也是非常精确的

关于曲线:我附近有一本大学的数值分析书,所以我只需要一个方法名和一个正确方向的轻推。我可以生成任意数量的点来近似曲线,但我希望将点的数量保持在一个有效的最小值。曲线始终为正/反曲线的一段形状,但不总是相同的曲线,并且始终小于一个周期。θ的范围是0°到359.999…°它有一些相位和振幅偏移,Y永远不会为负。此函数/算法必须快速运行,因为随着曲线的变化,它将每隔几百毫秒运行一次

如有任何建议,我们将不胜感激

编辑

关于曲线的更多信息:点是在鼠标移动时生成的。这些点是一组基于带惰轮的传动设计中橡胶带长度的点,如汽车中的蛇形皮带。惰轮的位置决定了皮带的长度,我得到了曲线[皮带长度(y)与惰轮位置(x)]。在这种情况下,惰轮为旋转惰轮,具有恒定的圆周运动。如果传动设计发生变化,则曲线将发生变化,原因可能是长度点发生变化,也可能是惰轮的运动范围受到限制。惰轮中的运动范围可能为0°至359.999…°,为θ,如上所述。对于开槽惰轮,最大范围为曲线周期的1/2(更容易出现问题)


我想我需要的是两种类型的托辊的通用解算器,但真正的问题是旋转托辊。

如果你有一个二次方程,那么最大值或最小值总是在方程的微分为0的点上。如果你的二次方程的公式是ax^2+bx+c=0,那么这个点就是x=-b/2a

是否为最大opr最小值可通过查看a来确定。如果a>0,则为最小值;如果a<0,则为最大值(如果a=0,则为非二次值)

我希望这有帮助。如果你还没有得到这种形式的曲线方程,你能说一下你从中得到了什么吗

编辑:问题已更改,因此曲线是正弦曲线的一部分,不再是二次曲线。因此,这个答案不再合适

Edit2:


对于正弦曲线,一般方程为y=a sin(mx+t)+c。你将永远无法精确地确定原始方程,因为对于任何解,都会有一个更高频率的解也匹配。我目前不确定需要多少点来精确计算a值(这将给出曲线的最小值和最大值)。

这组点是否都可用?这些点所代表的函数的“形状”没有限制吗?如果是这样的话,那么你可能会被困住,通过点迭代将是你最好的选择…
尽管如果您在这个集合上还有其他工作要做,您可能希望按Y坐标对其进行排序,以供将来处理使用

(将两个数组都放在周围—输入的数组(可能按x-corrd排序)和按函数值(y-coord)排序的数组)

编辑:如果知道曲线的形状总是“像”正/反曲线的一部分,那么如果知道可能表示的最小周期,可以使用二进制搜索算法“查找”拐点(斜率为(Y向左和向右的变化)具有不同的符号。对于左侧检查的每个点,向右移动分块=允许周期的一半,直到找到拐点,或坡度变化符号…然后向后移动x的一半,直到找到拐点。[对右侧的点执行相反的操作]

一个递归例程检查/找到第一个和最后一个拐点,比较它们以确定哪个拐点最大,然后递归检查并找到它们中间的影响点,直到涉及的两个点小于彼此之间的最小允许周期,将产生一些性能增益…

第二次编辑:因为我在你的其他评论中读到,集合将永远不会包含多个拐点……如果是这样,那么只需进行二进制搜索即可找到它

PsuedoCode:

  Check Leftmost point to see slope (Up Down or Zero)
       If Zero, done
  Check RightMost Slope 
       If Zero - Done
  If two Slopes are same sign - Done 
        - pick Bigger of two points ( - or smaller if looking for min)
  Check point in the Middle slope
     If Zero, Done
     If slope has same sign as left pt, Change Left to this Point and repeat
     If slope has same sign as right pt, Change Right to this Point and repeat

由于曲线总是二次的(因此总是凸的),应该有很多方法可用(虽然因为我没有用c#编程,我不知道源是否可用)。首先想到的是牛顿的方法,但还有其他方法(如内点法)。这些算法的数学背景(但不幸的是,不是它们的实现),请参阅教科书(pdf)。如果您确实使用这些方法中的任何一种,它们也适用于其他凸曲线。

您应该使用的算法(以及您给出的参数)这取决于你的数据集是什么样的。听起来你在评估一个连续获取的物理测量的波形

如果是这样,那么您需要决定是否要忽略局部最小值和最大值(例如信号中噪声的尖峰)。此外,您还需要某种方法来处理数据集的边缘。换句话说,t
    private void Test()
    {
        double[] X = SetLinearRange(0, Math.PI * 2, 1000);
        double[] Y = GetOutput(X);
        int MaxIndex = getMaxIndex(Y);
        double MaxX = X[MaxIndex];
        double MaxY = Y[MaxIndex];
    }
    private double[] SetLinearRange(double Start, double End, int Sample)
    {
        double Step = (End - Start) / Sample;
        double CurrentVaue = Start;
        double[] Array = new double[Sample];
        for (int Index = 0; Index < Sample; Index++)
        {
            Array[Index] = CurrentVaue;
            CurrentVaue += Step;
        }
        return Array;
    }
    private double[] GetOutput(double[] X)
    {
        double[] Array;
        Array = (from double Item in X select myFunction(Item)).ToArray();
        return Array;
    }
    private double myFunction(double x)
    {
        double y;
        //put any function
        y = 3 * Math.Sin(5 * x + 2);
        return y;
    }
    private int getMaxIndex(double[] Y)
    {
        double YM = Y.Max();
        int Index = Y.ToList().IndexOf(YM);
        return Index;
    }