累了的时候看看这个 |
用binary splitting算圆周率,把递归的算法改成循环后变慢了,为什么呢?
递归的代码
function bs(a, b) {
if (b - a == 1n) {
if (a == 0n)
Pab = Qab = 1n;
else {
Pab = (6n * a - 5n) * (2n * a - 1n) * (6n * a - 1n);
Qab = 9n * 106720n ** 3n * a ** 3n;
}
Tab = (13591409n + 545140134n * a) * Pab;
if (a & 1n)
Tab = -Tab;
return [Pab, Qab, Tab]
} else {
let m = (a + b) / 2n;
let[Pam,Qam,Tam] = bs(a, m);
let[Pmb,Qmb,Tmb] = bs(m, b);
Pab = Pam * Pmb;
Qab = Qam * Qmb;
Tab = Qmb * Tam + Pam * Tmb;
return [Pab, Qab, Tab]
}
}
改成循环的代码
function cbs(n) {
P = Q = 1n;
T = 13591409n;
i = 2n;
while (i <= n) {
Pm = (6n * i - 11n) * (2n * i - 3n) * (6n * i - 7n);
Qm = 9n * 106720n ** 3n * (i - 1n) ** 3n;
Tm = (-1n) ** i * (531548725n - i);
T = Qm * T + P * Tm;
P *= Pm;
Q *= Qm;
i++
}
return [P, Q, T]
}
不会贴代码?
function bs(a, b) {
if (b - a == 1n) {
if (a == 0n)
Pab = Qab = 1n;
else {
Pab = (6n * a - 5n) * (2n * a - 1n) * (6n * a - 1n);
Qab = 9n * 106720n ** 3n * a ** 3n;
}
Tab = (13591409n + 545140134n * a) * Pab;
if (a & 1n)
Tab = -Tab;
return [Pab, Qab, Tab]
} else {
let m = (a + b) / 2n;
let [Pam, Qam, Tam] = bs(a, m);
let [Pmb, Qmb, Tmb] = bs(m, b);
Pab = Pam * Pmb;
Qab = Qam * Qmb;
Tab = Qmb * Tam + Pam * Tmb;
return [Pab, Qab, Tab]
}
}
function cbs(n) {
P = Q = 1n;
T = 13591409n;
i = 2n;
while (i <= n) {
Pm = (6n * i - 11n) * (2n * i - 3n) * (6n * i - 7n);
Qm = 9n * 106720n ** 3n * (i - 1n) ** 3n;
Tm = (-1n) ** i * (531548725n - i);
T = Qm * T + P * Tm;
P *= Pm;
Q *= Qm;
i++
}
return [P, Q, T]
}
这段代码是计算一个数学公式中的三个参数 P、Q 和 T,具体的计算过程需要了解该数学公式的背景和含义。
以下是一些可能的优化建议:
在函数内部使用 let 或 const 关键字声明变量,避免全局变量的使用。
给变量加上合适的类型声明,例如 P = Q = 1n 可以改写为 let P: bigint = 1n, Q: bigint = 1n;。
在循环开始前进行一些预处理,例如先计算出 Qm 的值,减少循环内部运算的次数。
对于循环中的乘法运算,可以把多个因子组合成一个表达式,例如 (6n * i - 11n) * (2n * i - 3n) * (6n * i - 7n) 可以改写为 (12n * i ** 3n - 36n * i ** 2n + 23n * i - 3n)。
对于循环中的指数运算,可以使用位运算或者幂次预处理等技巧进行优化。
可以考虑在循环外部使用 BigInt() 函数将常量转换为 BigInt 类型,以提高计算效率。
综上所述,下面是经过优化的代码实现:
javascript
function cbs(n) {
let P = 1n, Q = 1n;
let T = BigInt(13591409);
let Qm = 9n * 106720n ** 3n;
for (let i = 2n; i <= n; i++) {
P = (12n * i * 3n - 36n * i ** 2n + 23n * i - 3n);
Q = Qm * (i - 1n) * 3n;
T += (-1n) ** i * BigInt(531548725 - i) * Q;
}
return [P, Q, T * 4270934400n];
}
这个实现中,我们将 Qm 的值在循环开始前计算出来,避免了多次重复计算。同时,在循环内部使用了更具有语义化的变量名,并且使用了 BigInt() 函数将常量转换为 BigInt 类型。除此之外,我们还把乘法运算进行了简化。
过早客微信公众号:guozaoke • 过早客新浪微博:@过早客 • 广告投放合作微信:fullygroup50 鄂ICP备2021016276号-2 • 鄂公网安备42018502001446号