如何手动实现基于加减乘除与循环的N进制对数计算?
我明白你想要手动实现对数计算的需求了——你的原代码确实只能算出对数的整数部分,没法得到精确的小数结果。咱们来一步步修正它,只用基础运算和循环搞定这个问题:
原代码的问题分析
你的代码逻辑是不断将x除以底数,直到x小于底数,累加的次数就是对数的整数部分,但完全忽略了剩下的小数部分。比如计算log₂(10)时,10除以2三次后得到1.25,这时候1.25<2,但这部分对应的log₂(1.25)≈0.3219并没有被计算,所以最终结果只返回了整数3,而非完整的3.3219...
修正后的完整实现
下面的代码会先计算整数部分,再通过迭代逼近的方式计算小数部分,完全只用+-*/和循环实现:
function myLog(base, x) { // 处理对数的定义域边界情况 if (base <= 0 || base === 1 || x <= 0) { return NaN; } // 处理底数在0-1之间的情况:转换为倒数底数,结果取反(log_{1/b}(x) = -log_b(x)) if (base < 1) { base = 1 / base; return -myLog(base, x); } let result = 0; let currentX = x; // 计算整数部分:处理x >= 底数的情况 while (currentX >= base) { currentX /= base; result++; } // 计算整数部分:处理x < 1的情况(此时对数结果为负数) while (currentX < 1) { currentX *= base; result--; } // 迭代计算小数部分,循环100次足够达到高精度 let fraction = 0; let power = 0.5; // 初始分数位为1/2,之后每次缩小一半:1/4、1/8... for (let i = 0; i < 100; i++) { currentX *= currentX; // 等价于 base^(2f) = currentX² if (currentX >= base) { currentX /= base; // 将currentX拉回[1, base)区间 fraction += power; // 累加当前有效的分数位 } power /= 2; // 下一个分数位缩小一半 } return result + fraction; } // 测试示例 console.log(myLog(2, 10)); // 输出约3.3219280949 console.log(myLog(5, 15)); // 输出约1.6826061945
小数部分的计算逻辑说明
当整数部分计算完成后,currentX会落在[1, base)区间内,我们需要找到小数部分f使得base^f = currentX:
- 每次将
currentX平方,相当于把指数翻倍(base^(2f) = currentX²) - 如果平方后的
currentX >= base,说明2f >= 1,即f >= 0.5,于是我们把0.5加入小数结果,再将currentX除以底数拉回[1, base)区间 - 之后将分数位缩小一半(变成0.25、0.125...),重复上述步骤,直到循环足够次数(100次已经能达到极高精度)
内容的提问来源于stack exchange,提问作者user3596335
相关产品推荐
相关产品推荐

