一个非线性级数的C#聚合函数

本文关键字:函数 一个 非线性 | 更新日期: 2023-09-27 18:00:06

我得到了两个数组,一个表示价格,另一个表示多个单位:

例如

decimal[] price = new decimal[] {1.65, 1.6, 1.55, 1.4, 1.3};
long[] quantity = new long[] {5000, 10000, 12000, 20000, 50000};

因此,前5000台每台售价1.65美元,下一台售价10000美元每台售价1.6美元,以此类推…

当你知道你想要订购的单位数量时,用聚合函数很容易得到平均价格。例如,7000单位的平均价格=(5000/7000*1.65)+(2000/7000*1.6),然而,当总单位数量是未知变量时,我很难想出一个算法,我们得到了目标平均价格。

例如,我必须订购多少台,这样平均单价=1.57

一个非线性级数的C#聚合函数

如果你从几何角度考虑,可以考虑一张图表,显示总价格(纵轴)是购买物品总数(横坐标)的函数。情节从(0, 0)开始(零购买零成本)。首先得到一条斜率为1.65、水平宽度为5000的直线段。然后,从其终点来了斜率为1.6和宽度为10000的新的段。总的地块是连续的、分段的直线,但在单价变化的地方有弯曲。

然后,为了解决您的问题,找到与方程y == 1.57 * x的线的交点,即从(0, 0)开始并具有斜率1.57的线。对于每个分段(您知道其两个端点),检查该分段是否满足y == 1.57 * x,如果满足,则有您的解决方案。

如果price数组中的数字在减少,则最多可以有一个解决方案(假设1.57严格小于第一个价格price[0]),该图表示凹函数。

编辑:我试图用C#对这个几何体进行编码。我没有加上price都是正的和递减的,以及quantity都是正。你必须检查一下。这是我的代码:

        decimal[] price = { 1.65m, 1.6m, 1.55m, 1.4m, 1.3m, };
        long[] quantity = { 5000, 10000, 12000, 20000, 50000, };
        decimal desiredAverage = 1.57m;
        int length = price.Length;
        if (length != quantity.Length)
            throw new InvalidOperationException();
        var abscissaValues = new long[length + 1];
        var ordinateValues = new decimal[length + 1];
        for (int i = 1; i <= length; ++i)
        {
            for (int j = 0; j < i; ++j)
            {
                abscissaValues[i] += quantity[j];
                ordinateValues[i] += price[j] * quantity[j];
            }
        } // calculation of plot complete
        int segmentNumber = Enumerable.Range(1, length).FirstOrDefault(i => ordinateValues[i] / abscissaValues[i] <= desiredAverage);
        if (segmentNumber > 1)
        {
            decimal x = (ordinateValues[segmentNumber - 1] * abscissaValues[segmentNumber] - abscissaValues[segmentNumber - 1] * ordinateValues[segmentNumber])
                / (desiredAverage * (abscissaValues[segmentNumber] - abscissaValues[segmentNumber - 1]) - (ordinateValues[segmentNumber] - ordinateValues[segmentNumber - 1]));
            Console.WriteLine("Found solution x == " + x);
        }
        else
        {
            Console.WriteLine("No solution");
        }

我不知道是否有人能把它写得更漂亮,但它似乎奏效了。输出为:

找到的溶液x==29705.882352941176470588235294

我相信这是因为没有一个答案,没有一个价格组合,这将导致的一个平均值,没有闭合形式的方程。我们可能看到的是背包问题的一个变体。http://en.wikipedia.org/wiki/Knapsack_problem其具有值的最小化而不是最大化。

编辑:正如下面正确指出的,这不是背包问题的变体。有一个封闭形式的解决方案:

如果T=购买的总单位,

1.57=1.55*(12000/T)+1.6*(T-12000)/T)。求解T.

起始价格块(此处为1.55)是略低于问题中给出的单位平均价格(此处为1.507)的块。