比如计算百分比,乘除法,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