如何在 JavaScript 中求数字序列的总和

Dum*_*ing 2 javascript

for (var x = 0; x < 10; x++) {\n    if (x % 3 === 0 || x % 5 === 0) {\n        console.log(x)\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

这会打印出:0,3,5,6,9。我想要一个输出\xe2\x80\x94总和,或23\xe2\x80\x94并打印一次console.log,而不是单独打印每个术语。

\n\n

我怎样才能找到这个序列的总和?

\n

roy*_*wie 6

循环固然很好,但这个问题实际上只是数学问题。我们可以做得更好,在常数时间内求和。

等差数列是指项之间的差恒定时的数列。例如,

1, 2, 3, 4, 5...
Run Code Online (Sandbox Code Playgroud)

是一个算术数列d,其中项之间的差为 1。

0, 2, 4, 6, 8...
Run Code Online (Sandbox Code Playgroud)

是ad为2的算术数列。

如果我们看一下我们的序列:

0, 3, 5, 6, 9...
Run Code Online (Sandbox Code Playgroud)

我们很快就能看到有两个重叠的算术序列(3n5n):

0, 5, 10, 15... and 0, 3, 6, 9, 12, 15...
Run Code Online (Sandbox Code Playgroud)

然后我们可以很快看到共享项是 15 的倍数。

求总和比看起来容易。我们可以使用有史以来最伟大的数学家之一卡尔·弗里德里希·高斯(Karl Friedrich Gauss)在很小的时候就凭直觉(但没有发现)的方法(iirc,6 岁)。

让我们再看看我们的3n序列:

0, 3, 6, 9, 12, 15...
Run Code Online (Sandbox Code Playgroud)

你看到一个模式了吗?如果我们抽对,从每一端取一个数字......

0 and 15
3 and 12
6 and 9
Run Code Online (Sandbox Code Playgroud)

我们最终得到常数和 15。由此,我们可以得出一个公式。

有多少对?n / 2,其中n是项数。

每对的总和是多少?a1 + aN,其中a1是第一项,aN是最后一项。

这意味着我们的总和是

S = (n / 2) * (a1 + aN)
Run Code Online (Sandbox Code Playgroud)

我们快到了。如果我们将两个序列的和相加,我们会得到一点额外的结果。为什么?

0, 3, 6, 9, 12, 15...
0, 5, 10, 15...
Run Code Online (Sandbox Code Playgroud)

我们数15的倍数两次!但这很容易解释:

grandTotal = sum3 + sum5 - sum15
Run Code Online (Sandbox Code Playgroud)

我们的解决方案(您可能更感兴趣arithmeticProgression):

/*
    finds the sum of two arithmetic sequences, on [min, max] (inclusive)
    for two numbers a and b
*/
function getSum (min, max, a, b) {    
    function arithmeticProgression (start, stop, m) {
        // find the nearest multiple of m greater than or equal to the starting bound
        start = m * Math.ceil(start / m)

        // find the nearest multiple of m less than or equal to the ending bound
        stop = m * Math.floor(stop / m)

        // the number of terms, e.g., in 0, 2, 4, 6, 8
        // we have 5 terms because of (max - min)/delta + 1
        // or, ((8 - 0) / 2) + 1 = 4 + 1 = 5
        var terms = ((stop - start) / m) + 1

        // our formula from before
        return (terms / 2) * (start + stop)
    }
    var sum3 = arithmeticProgression(min, max, a)
    var sum5 = arithmeticProgression(min, max, b)
    var sum15 = arithmeticProgression(min, max, a * b)

    return sum3 + sum5 - sum15
}
Run Code Online (Sandbox Code Playgroud)

测试:

console.log(getSum(0, 9, 3, 5) === 23)   // true
Run Code Online (Sandbox Code Playgroud)