(请参阅下面的解决方案)

(潜伏者出现)

我正在使用BigDecimal / BigInteger类来处理非常大的数字。

我有一个计算复合增长级数的公式。

对于每个n,值=初始*(coef ^ n)。

我正在尝试找到一种快速的方法来计算n0和n1之间的值的子集的总和。

例如n0 = 4且n1 = 6

返回值:初始*(coef ^ 4)+初始*(coef ^ 5)+初始*(coef ^ 6)

我对数学不太了解,但是也许有一种表达方式?

我基本上是将所有值加起来,通过提高系数将其中一些乘以10的幂。

据我所知,该功能是准确的。我可以返回一个值

n0 = 1,n1 = 50000,初始值= 100,coef = 1.05英寸。

尽管我可能永远不会将函数用于大于20,000的值,但是很高兴知道是否有更有效的方法。

public static final BigDecimal sum(int n0, int n1, BigDecimal initial, BigDecimal coef) {
    BigDecimal sum = BigDecimal.ZERO;

    int short_cut = 1000000000;

    //Loop for each power of 10
    while (short_cut >= 10) {
        //Check the range of n is greater than the power of 10
        if (n1 - n0 >= short_cut) {
            //Calculate the coefficient * the power of 10
            BigDecimal xCoef = coef.pow(short_cut);

            //Add the first sum of values for n by re-calling the function for n0 to n0 + shortcut - 1
            BigDecimal add = sum(n0, n0 + short_cut - 1, initial, coef);
            sum = sum.add(add);

            //Move n forward by the power of 10
            n0 += short_cut;

            while (n1 - n0 >= short_cut) {
                //While the range is still less than the current power of 10
                //Continue to add the next sum multiplied by the coefficient
                add = add.multiply(xCoef);
                sum = sum.add(add);
                //Move n forward
                n0 += short_cut;
            }

        }
        //Move to the next smallest power of 10
        short_cut /= 10;
    }

    //Finish adding where n is smaller than 10
    for (; n0 <= n1; n0++)
        sum = sum.add(initial.multiply(coef.pow(n0)));
    return sum;
}


下一个问题是求出n1的最大值,其中sum(n0,initial,coef)
编辑:

public static final BigDecimal sum(int n0, int n1, BigDecimal initial, BigDecimal coef) {
    return initial.multiply(coef.pow(n0).subtract(coef.pow(n1 + 1))).divide(BigDecimal.ONE.subtract(coef));
}


(初始* coef ^ n0-coef ^ n1 + 1)/ 1-coef

谢谢维基百科。

最佳答案

我会写一些算法思想。

首先,让您简化公式:

因此,您应该计算:S = a *(c ^ n0)+ a *(c ^(n0 + 1))+ ... + a *(c ^ n1)
其中initial = a和coef = c

令S(n)为以下和的函数:
S(n)= a + a * c + a *(c ^ 2)+ ... + a *(c ^ n)

我们将得到S = S(n1)-S(n0-1)

另一方面,S(n)是geometric progression的和,因此S(n)= a *(1-c ^ n)/(1-c)。

所以我们将得到S = S(n1)-S(n0-1)= a *(1-c ^ n1)/(1-c)-a *(1-c ^(n0-1))/(1 -c)= a *(c ^(n0-1)-c ^ n1)/(1-c)。

因此,现在我们必须处理计算c ^ n指数(当然BigDecimal类具有pow方法,我们这样做是为了能够计算算法的复杂性)。以下算法具有O(log(n))复杂度:

function exp(c,n){
    // throw exception when n is not an natural number or 0
    if(n == 0){
        return 1;
    }
    m = exp(c, floor(n/2));
    if (n % 2 == 0){
        return m*m;
    } else{
        return m*m*c;
    }
}


因此,如果考虑代数运算具有O(1)复杂度这一事实,我们可以得出结论,可以以O(log(n))复杂度计算总和。

关于java - 计算指数增长序列中的值之和,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36991866/

10-09 09:43