比如计算百分比,乘除法,js计算有小数点,精度会丢失,通过toFixed可以截取小数后几位,但是会四舍五入,而toPrecision则需要指定数字长度。现在要保留小数点后2位,请问怎么处理
let n = 123.123; console.log(n.toPrecision(4)) // 123.1
let n = 123.126; console.log(n.toFixed(2)) // 123.13
期望结果:
let n = 123.1266646635525563;
// 123.12
所谓“没有完美的算法,只有合适的场景”,浮点数字(小数)就是个很好的例子。
我们知道,按照目前的规范,JS 无法直接完美的处理小数。但是实际上,我们往往也不需要它“完美”处理小数。比如,以记账为例,我们通常只关心小数点后两位,也就是“分”,再细的,我们关注它意义不大,投入产出比太低。那么我们就可以把所有数字 * 100,取整后保存,带来的误差非常低。
所以,讨论小数精度问题,要看具体的需求。只要满足需求,怎么保存都可以。
自定义计算函数:
function multiply(a, b) { let m = 0; const s1 = a.toString(); const s2 = b.toString(); try { m += s1.split(".")[1].length } catch (e) {} try { m += s2.split(".")[1].length } catch (e) {} return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m); } function divide(a, b) { let t1 = 0; let t2 = 0; try { t1 = a.toString().split(".")[1].length } catch (e) {} try { t2 = b.toString().split(".")[1].length } catch (e) {} const r1 = Number(a.toString().replace(".", "")); const r2 = Number(b.toString().replace(".", "")); return multiply((r1 / r2), Math.pow(10, t2 - t1)); } function add(a, b) { let c = 0; let d = 0; try { c = a.toString().split(".")[1].length } catch (e) {} try { d = b.toString().split(".")[1].length } catch (e) {} const m = Math.pow(10, Math.max(c, d)); return (multiply(a, m) + multiply(b, m)) / m; } function subtract(a, b) { let c = 0; let d = 0; try { c = a.toString().split(".")[1].length } catch (e) {} try { d = b.toString().split(".")[1].length } catch (e) {} const m = Math.pow(10, Math.max(c, d)); const n = (c >= d) ? c : d; return ((multiply(a, m) - multiply(b, m)) / m).toFixed(n); } let n = 123.1266646635525563; let result = multiply(n, 100); result = Math.floor(result); result = divide(result, 100); console.log(result); // 123.12