在工作中经常需要进行数字运算,当然也会遇到浮点型数字的运算,但是运算结果却并不是想要。
这种小孩子都会做的简单运算,强大的计算居然算算错?原来,计算机的运算都需要转成二制运算,而二进制和实现位数限制有些数无法有限表示。
比如:以下是十进制小数对应的二进制表示
0.1 >> 0.0001 1001 1001 1001…(1001无限循环) 0.2 >> 0.0011 0011 0011 0011…(0011无限循环
计算机里每种数据类型的存储是一个有限宽度,比如 JavaScript 使用 64 位存储数字类型,因此超出的会舍去。舍去的部分就是精度丢失的部分。
那小数计算会有问题,那把数字转整数来计算不就可以了吗?
/* ===== 浮点型数据的加、减、乘、除 ===== */ function add(arg1, arg2) { // 加法 let r1, r2, m try { r1 = arg1.toString().split('.')[1].length } catch (e) { r1 = 0 } try { r2 = arg2.toString().split('.')[1].length } catch (e) { r2 = 0 } m = Math.pow(10, Math.max(r1, r2)) return (arg1 * m + arg2 * m) / m } function sub(arg1, arg2) { // 减法 let r1, r2, m, n try { r1 = arg1.toString().split('.')[1].length } catch (e) { r1 = 0 } try { r2 = arg2.toString().split('.')[1].length } catch (e) { r2 = 0 } m = Math.pow(10, Math.max(r1, r2)) n = (r1 >= r2) ? r1 : r2 return ((arg1 * m - arg2 * m) / m).toFixed(n) } function mul(arg1, arg2) { // 乘法 let m = 0 let s1 = arg1.toString() let s2 = arg2.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 div(arg1, arg2) { // 除法 let t1 = 0 let t2 = 0 let r1 let r2 try { t1 = arg1.toString().split('.')[1].length } catch (e) { } try { t2 = arg2.toString().split('.')[1].length } catch (e) { } r1 = Number(arg1.toString().replace('.', '')) r2 = Number(arg2.toString().replace('.', '')) let intDiv = r1 / r2 let pow = Math.pow(10, t2 - t1) return mul(intDiv, pow) // 这里用上面定义好的乘法运算 } /* ===== 浮点型数据的加、减、乘、除 ===== */