<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[刘新修]]></title> 
<link>http://pic1.liuxinxiu.com:80/index.php</link> 
<description><![CDATA[刘新修的个人博客 (Liuxinxiu'S Blog)]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[刘新修]]></copyright>
<item>
<link>http://pic1.liuxinxiu.com:80/s//</link>
<title><![CDATA[解决JS两数相加的精度问题]]></title> 
<author>刘新修 &lt;admin@yourname.com&gt;</author>
<category><![CDATA[H5/JS/CSS]]></category>
<pubDate>Thu, 11 Jul 2024 00:40:55 +0000</pubDate> 
<guid>http://pic1.liuxinxiu.com:80/s//</guid> 
<description>
<![CDATA[ 
	<h3 style="box-sizing: border-box; outline: 0px; padding: 0px; font-family: &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, SimHei, Arial, SimSun; font-size: 18px; color: rgb(79, 79, 79); line-height: 28px; font-synthesis-style: auto; overflow-wrap: break-word; font-variant-ligatures: no-common-ligatures;">JS中小数相加存在的精度问题</h3><p style="box-sizing: border-box; outline: 0px; margin-bottom: 16px; font-size: 16px; color: rgb(77, 77, 77); line-height: 26px; overflow: auto hidden; font-synthesis-style: auto; overflow-wrap: break-word; font-family: -apple-system, &quot;SF UI Text&quot;, Arial, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-variant-ligatures: no-common-ligatures;">首先来看一段示例：</p><div class="codeText"><div class="codeHead">JavaScript代码</div><ol start="1" class="dp-c"><li class="alt"><span><span>console.log(0.1+0.2);</span><span class="comment">//0.30000000000000004</span><span>&nbsp;&nbsp;</span></span></li><li><span>console.log(0.2+0.7);<span class="comment">//0.8999999999999999</span><span>&nbsp;&nbsp;</span></span></li></ol></div><p style="box-sizing: border-box; outline: 0px; margin-bottom: 16px; line-height: 26px; overflow: auto hidden; font-synthesis-style: auto; overflow-wrap: break-word;"><font color="#4d4d4d" face="-apple-system, SF UI Text, Arial, PingFang SC, Hiragino Sans GB, Microsoft YaHei, WenQuanYi Micro Hei, sans-serif"><span style="font-size: 16px; font-variant-ligatures: no-common-ligatures;">JS中两数小数相加产生精度问题的原因：</span></font></p><p style="box-sizing: border-box; outline: 0px; margin-bottom: 16px; line-height: 26px; overflow: auto hidden; font-synthesis-style: auto; overflow-wrap: break-word;"><font color="#4d4d4d" face="-apple-system, SF UI Text, Arial, PingFang SC, Hiragino Sans GB, Microsoft YaHei, WenQuanYi Micro Hei, sans-serif"><span style="font-size: 16px; font-variant-ligatures: no-common-ligatures;">1、js中的数字类型只有number类型，不区分浮点型和整形，直接以浮点型double类型（双精度浮点类型）参与运算。</span></font></p><p style="box-sizing: border-box; outline: 0px; margin-bottom: 16px; line-height: 26px; overflow: auto hidden; font-synthesis-style: auto; overflow-wrap: break-word;"><font color="#4d4d4d" face="-apple-system, SF UI Text, Arial, PingFang SC, Hiragino Sans GB, Microsoft YaHei, WenQuanYi Micro Hei, sans-serif"><span style="font-size: 16px; font-variant-ligatures: no-common-ligatures;">2、十进制数在做加减法运算前，首先转换为二进制类型再做相加减运算。</span></font></p><p style="box-sizing: border-box; outline: 0px; margin-bottom: 16px; line-height: 26px; overflow: auto hidden; font-synthesis-style: auto; overflow-wrap: break-word;"><font color="#4d4d4d" face="-apple-system, SF UI Text, Arial, PingFang SC, Hiragino Sans GB, Microsoft YaHei, WenQuanYi Micro Hei, sans-serif"><span style="font-size: 16px; font-variant-ligatures: no-common-ligatures;">3、一些浮点数在转换为二进制数是会出现无线循环的情况，但由于double数据类型是以64位存储表示一个数据，其中第1位为符号位，第2位到第12位为指数位，其余52位为小数位，如此一来，一些浮点数转换为二进制产生无限循环的情况下，double类型数据只能存储64位，所以产生精度缺失问题。</span></font></p><h3 style="box-sizing: border-box; outline: 0px; padding: 0px; font-family: &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, SimHei, Arial, SimSun; font-size: 18px; color: rgb(79, 79, 79); line-height: 28px; font-synthesis-style: auto; overflow-wrap: break-word; font-variant-ligatures: no-common-ligatures;">解决办法</h3><p style="box-sizing: border-box; outline: 0px; margin-bottom: 16px; font-size: 16px; color: rgb(77, 77, 77); line-height: 26px; overflow: auto hidden; font-synthesis-style: auto; overflow-wrap: break-word; font-family: -apple-system, &quot;SF UI Text&quot;, Arial, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-variant-ligatures: no-common-ligatures;">该方法仅为其中一个办法：</p><div class="codeText"><div class="codeHead">JavaScript代码</div><ol start="1" class="dp-c"><li class="alt"><span><span>&lt;script&gt;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">// 精确乘法计算</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">function</span><span> FloatMul(arg1, arg2) &#123;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">var</span><span> m = 0,&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s1 = arg1.toString(),<span class="comment">//将第一个数据转换成字符出类型</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s2 = arg2.toString();<span class="comment">//将第二个数据转换成字符出类型</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">try</span><span> &#123;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m += s1.split(<span class="string">&quot;.&quot;</span><span>)[1].length;</span><span class="comment">//截取数据的小数部分，得到小数位数</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125; <span class="keyword">catch</span><span> (e) &#123;&#125;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">try</span><span> &#123;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m += s2.split(<span class="string">&quot;.&quot;</span><span>)[1].length;</span><span class="comment">//截取数据的小数部分，得到小数位数</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//将两个数据的小数位数长度相加</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125; <span class="keyword">catch</span><span> (e) &#123;&#125;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">var</span><span> result = (Number(s1.replace(</span><span class="string">&quot;.&quot;</span><span>, </span><span class="string">&quot;&quot;</span><span>)) * Number(s2.replace(</span><span class="string">&quot;.&quot;</span><span>, </span><span class="string">&quot;&quot;</span><span>))) / Math.pow(10, m);</span><span class="comment">//将两个数扩大对应的小数位数倍转换成数字类型在相乘，乘完再除于对应的扩大倍数得到最终结果</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span> isNaN(result) ? 0 : result;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//获得两个小数相加的精确值</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">const</span><span> accountAdd = (arg1, arg2) =&gt; &#123;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;let r1, r2, m;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">try</span><span> &#123;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r1 = arg1.toString().split(<span class="string">&quot;.&quot;</span><span>)[1].length;</span><span class="comment">//将第一个数据转换成字符出类型，截取数据的小数部分，得到小数位数</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125; <span class="keyword">catch</span><span> (e) &#123;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r1 = 0;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">try</span><span> &#123;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r2 = arg2.toString().split(<span class="string">&quot;.&quot;</span><span>)[1].length;</span><span class="comment">//将第一个数据转换成字符出类型，截取数据的小数部分，得到小数位数</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125; <span class="keyword">catch</span><span> (e) &#123;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r2 = 0;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m = Math.pow(10, Math.max(r1, r2));<span class="comment">//取出得到的最长位数，将10扩大最长位数倍</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span> (FloatMul(arg1, m) + FloatMul(arg2, m)) / m;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;let sum = accountAdd(2.3443, -1.987);&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;console.log(sum);<span class="comment">//0.3573</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/script&gt;&nbsp;&nbsp;</span></li></ol></div><p style="box-sizing: border-box; outline: 0px; margin-bottom: 16px; line-height: 26px; overflow: auto hidden; font-synthesis-style: auto; overflow-wrap: break-word;"><font color="#4d4d4d" face="-apple-system, SF UI Text, Arial, PingFang SC, Hiragino Sans GB, Microsoft YaHei, WenQuanYi Micro Hei, sans-serif"><span style="font-size: 16px; font-variant-ligatures: no-common-ligatures;">思路：</span></font></p><p style="box-sizing: border-box; outline: 0px; margin-bottom: 16px; line-height: 26px; overflow: auto hidden; font-synthesis-style: auto; overflow-wrap: break-word;"><font color="#4d4d4d" face="-apple-system, SF UI Text, Arial, PingFang SC, Hiragino Sans GB, Microsoft YaHei, WenQuanYi Micro Hei, sans-serif"><span style="font-size: 16px; font-variant-ligatures: no-common-ligatures;">1、先将两个小数数据用精确乘法扩大相同倍数，扩大后相加再处于扩大倍数得到最后结果。</span></font></p>
]]>
</description>
</item><item>
<link>http://pic1.liuxinxiu.com:80/s//#blogcomment</link>
<title><![CDATA[[评论] 解决JS两数相加的精度问题]]></title> 
<author> &lt;user@domain.com&gt;</author>
<category><![CDATA[评论]]></category>
<pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate> 
<guid>http://pic1.liuxinxiu.com:80/s//#blogcomment</guid> 
<description>
<![CDATA[ 
	
]]>
</description>
</item>
</channel>
</rss>