调整计算精度
Posted 行似深夜
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了调整计算精度相关的知识,希望对你有一定的参考价值。
问题由来:js 数字存储采用 IEEE754 标准,该标准用 64 位二进制数存储一个浮点数,即一个数字占用的内存是 8bytes,因此在存储一个无限大的数字时就会存在精度损失。对于像 0.1 这样的浮点数来说,无法用二进制的方式精确表示,这是由计算方式本身决定的,因此这部分浮点数的存储精度丢失是必然的,和语言、存储方式、内存大小没有关系。当然,像 0.5 这种可以用二进制精确表示,并且大小不超过 2** 53 的浮点数是可以精确存储的。IEEE754 的存储方式是,最高位是符号位,0 表示正,1表示负,接下来是 11 位指数位,接下来是 52 位小数位,二进制的科学计数法,它的整数部分固定是 1,所以 1 个整数位加上 52 的小数位,最大可以表示 2**53,因此即使是整数,如果超出这个范围,存储精度也是要损失的。
思路:刚才说一个无穷数的存储是有问题的,如果我们把浮点数当作整数计算,计算完成后再转换为字符串类型的小数存储是不是就可以了。
实现:
function add(a, b) a = a.toString(), b = b.toString(); const r0 = a.includes(\'.\') ? a.length - (a.indexOf(\'.\') + 1) : ((a += \'.\'), 0), r = b.includes(\'.\') ? b.length - (b.indexOf(\'.\') + 1) : ((b += \'.\'), 0); if (r0 > r) b += \'0\'.repeat(r0 - r); if (r > r0) a += \'0\'.repeat(r - r0); return (+a.replace(\'.\', \'\') + +b.replace(\'.\', \'\')) / 10 ** Math.max(r0, r); function sub(a, b) return add(a, -b); function mul(a, b) a = a.toString(), b = b.toString(); const r0 = a.includes(\'.\') ? a.length - (a.indexOf(\'.\') + 1) : ((a += \'.\'), 0), r = b.includes(\'.\') ? b.length - (b.indexOf(\'.\') + 1) : ((b += \'.\'), 0); if (r0 > r) b += \'0\'.repeat(r0 - r); if (r > r0) a += \'0\'.repeat(r - r0); return (+a.replace(\'.\', \'\') * +b.replace(\'.\', \'\')) / (10 ** Math.max(r0, r)) ** 2; function div(a, b) a = a.toString(), b = b.toString(); const r0 = a.includes(\'.\') ? a.length - (a.indexOf(\'.\') + 1) : ((a += \'.\'), 0), r = b.includes(\'.\') ? b.length - (b.indexOf(\'.\') + 1) : ((b += \'.\'), 0); if (r0 > r) b += \'0\'.repeat(r0 - r); if (r > r0) a += \'0\'.repeat(r - r0); return +a.replace(\'.\', \'\') / +b.replace(\'.\', \'\'); export add, sub, mul, div ;
以上是关于调整计算精度的主要内容,如果未能解决你的问题,请参考以下文章
QueryPerformanceFrequency使用方法--Windows高精度定时计数