十进制转二进制
整数采用 除2取余(由下往上)的方式,
57
57 / 2 = 28 … 1 28 / 2 = 14 … 0 14 / 2 = 7 … 0 7 / 2 = 3 … 1 3 / 2 = 1 … 1 1
111001
26
26 / 2 = 13 … 0 13 / 2 = 6 … 1 6 / 2 = 3 … 0 3 / 2 = 1 … 1 1
11010
小数采用 乘2取整(由上往下)的方式
0.1
.1 2 = 0.2 … 0 .2 2 = 0.4 … 0 .4 2 = 0.8 … 0 .8 2 = 1.6 … 1 .6 2 = 1.2 … 1 .2 2 = 0.4 … 0 .4 2 = 0.8 … 0 .8 2 = 1.6 … 1 .6 2 = 1.2 … 1 .2 2 = 0.4 … 0 .4 * 2 = 0.8 … 0 …
0.0001100110011001100110011001100 … 11001100
为什么会出现精度损失的情况
JavaScript 使用 Number 类型来表示数字(整数或浮点数),遵循 IEEE 754 标准,通过 64 位来表示一个数字。
两数相加时,会先转换成二进制
0.1 和 0.2 转换为二进制的时候尾数会无限循环
0.1 -> 0.0001100110011001100110011001100110011001100110011001101 0.2 -> 0.0011001100110011001100110011001100110011001100110011010
然后进行对阶运算,JS 引擎会对二进制进行截断,所以造成精度损失。
精度丢失可能出现在进制转换和对阶运算中。 如果不考虑精度,还可以用 toFixed 进行进制转化。 Number.parseFloat(x).toFixed(2);
如何解决精度丢失问题?
将数字转为整数
function add(num1, num2) {
const num1Digits = (num1.toString().split('.')[1] || '').length;
const num2Digits = (num2.toString().split('.')[1] || '').length;
const baseNum = Math.pow(10, Math.max(num1Digits, num2Digits));
return (num1 * baseNum + num2 * baseNum) / baseNum;
}
使用第三方库
正确的比较方法
Math.abs(0.1 + 0.2 - 0.3) <= Number.EPSILON