调整计算精度

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
 ;

 

以上是关于调整计算精度的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript 浮点数及运算精度调整总结

QueryPerformanceFrequency使用方法--Windows高精度定时计数

Abaqus如何对模型局部做更细密的网格划分

Matlab,如何调整图形上的轴值(科学记数法 - 精度不够)[重复]

灵活调整CAN总线负载 ,精度控制1%以内,且高可用

灵活调整CAN总线负载 ,精度控制1%以内,且高可用