js处理小数误差 https://www.e-learn.cn/tag/jschulixiaoshuwucha zh-hans javascript避免数字计算精度误差的方法详解 https://www.e-learn.cn/topic/186791 <span>javascript避免数字计算精度误差的方法详解</span> <span><span lang="" about="/user/99" typeof="schema:Person" property="schema:name" datatype="">牧云@^-^@</span></span> <span>2019-11-26 23:15:21</span> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"> <p><strong>本篇文章主要是对javascript避免数字计算精度误差的方法进行了介绍,需要的朋友可以过来参考下,希望对大家有所帮助</strong></p> <p style="margin-top: 0px; margin-bottom: 0px; padding: 5px 0px;">如果我问你 0.1 + 0.2 等于几?你可能会送我一个白眼,0.1 + 0.2 = 0.3 啊,那还用问吗?连幼儿园的小朋友都会回答这么小儿科的问题了。但是你知道吗,同样的问题放在编程语言中,或许就不是想象中那么简单的事儿了。<br />不信?我们先来看一段 JS。</p> <p style="margin-top: 0px; margin-bottom: 0px; padding: 5px 0px;"><strong>var numA = 0.1; <br />var numB = 0.2; <br />alert( (numA + numB) === 0.3 );</strong></p> <p style="margin-top: 0px; margin-bottom: 0px; padding: 5px 0px;">执行结果是 <strong>false</strong>。没错,当我第一次看到这段代码时,我也理所当然地以为它是 true,但是执行结果让我大跌眼镜,是我的打开方式不对吗?非也非也。我们再执行以下代码试试就知道结果为什么是 false 了。</p> <p style="margin-top: 0px; margin-bottom: 0px; padding: 5px 0px;"><strong>var numA = 0.1; <br />var numB = 0.2; <br />alert( numA + numB );</strong></p> <p style="margin-top: 0px; margin-bottom: 0px; padding: 5px 0px;">原来,<strong>0.1 + 0.2 = 0.30000000000000004</strong>。是不是很奇葩?其实对于浮点数的四则运算,几乎所有的编程语言都会有类似精度误差的问题,只不过在 C++/C#/Java 这些语言中已经封装好了方法来避免精度的问题,而 JavaScript 是一门弱类型的语言,从设计思想上就没有对浮点数有个严格的数据类型,所以精度误差的问题就显得格外突出。下面就分析下为什么会有这个精度误差,以及怎样修复这个误差。</p> <p style="margin-top: 0px; margin-bottom: 0px; padding: 5px 0px;">首先,我们要站在计算机的角度思考 0.1 + 0.2 这个看似小儿科的问题。我们知道,能被计算机读懂的是二进制,而不是十进制,所以我们先把 0.1 和 0.2 转换成二进制看看:</p> <p style="margin-top: 0px; margin-bottom: 0px; padding: 5px 0px;">0.1 =&gt; 0.0001 1001 1001 1001…(无限循环)<br />0.2 =&gt; 0.0011 0011 0011 0011…(无限循环)</p> <p style="margin-top: 0px; margin-bottom: 0px; padding: 5px 0px;">双精度浮点数的小数部分最多支持 52 位,所以两者相加之后得到这么一串 0.0100110011001100110011001100110011001100110011001100 因浮点数小数位的限制而截断的二进制数字,这时候,我们再把它转换为十进制,就成了 0.30000000000000004。</p> <p style="margin-top: 0px; margin-bottom: 0px; padding: 5px 0px;">原来如此,那怎么解决这个问题呢?我想要的结果就是 0.1 + 0.2 === 0.3 啊!!!</p> <p style="margin-top: 0px; margin-bottom: 0px; padding: 5px 0px;">有种最简单的解决方案,就是给出明确的精度要求,在返回值的过程中,计算机会自动四舍五入,比如:</p> <p style="margin-top: 0px; margin-bottom: 0px; padding: 5px 0px;"><strong>var numA = 0.1; <br />var numB = 0.2; <br />alert( parseFloat((numA + numB).toFixed(2)) === 0.3 );</strong></p> <p style="margin-top: 0px; margin-bottom: 0px; padding: 5px 0px;">但是明显这不是一劳永逸的方法,如果有一个方法能帮我们解决这些浮点数的精度问题,那该多好。我们来试试下面这个方法:</p> <p style="margin-top: 0px; margin-bottom: 0px; padding: 5px 0px;"><span style="font-size: 16px;"><strong>Math.formatFloat = function(f, digit) { <br />    var m = Math.pow(10, digit); <br />    return parseInt(f * m, 10) / m; <br />} <br /><br />var numA = 0.1; <br />var numB = 0.2;</strong></span></p> <p style="margin-top: 0px; margin-bottom: 0px; padding: 5px 0px;"><span style="font-size: 16px;"><strong>alert(Math.formatFloat(numA + numB, 1) === 0.3);</strong></span></p> <p style="margin-top: 0px; margin-bottom: 0px; padding: 5px 0px;">这个方法是什么意思呢?为了避免产生精度差异,我们要把需要计算的数字乘以 10 的 n 次幂,换算成计算机能够精确识别的整数,然后再除以 10 的 n 次幂,大部分编程语言都是这样处理精度差异的,我们就借用过来处理一下 JS 中的浮点数精度误差。</p> <p style="margin-top: 0px; margin-bottom: 0px; padding: 5px 0px;">如果下次再有人问你 0.1 + 0.2 等于几,你可要小心回答咯!!</p> <p><br /></p> <div class="alert alert-success" role="alert"><p>来源:<code>oschina</code></p><p>链接:<code>https://my.oschina.net/u/1378869/blog/359103</code></p></div></div> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field--label">标签</div> <div class="field--items"> <div class="field--item"><a href="/tag/jschulixiaoshuwucha" hreflang="zh-hans">js处理小数误差</a></div> </div> </div> Tue, 26 Nov 2019 15:15:21 +0000 牧云@^-^@ 186791 at https://www.e-learn.cn