Javascript浮点数陷阱:修订间差异
来自三线的随记
(创建页面,内容为“调试JavaScript代码的时候涉及了浮点数运算 出现了很奇怪的结果<blockquote>> 5.1+2.55</blockquote><blockquote>> 7.6499999999999995</blockquote>…”) |
无编辑摘要 |
||
(未显示同一用户的1个中间版本) | |||
第11行: | 第11行: | ||
=== 数据展示类 === | === 数据展示类 === | ||
当你拿到 <code>1.4000000000000001</code> 这样的数据要展示时,建议使用 <code>toPrecision</code> 凑整并 <code>parseFloat</code> 转成数字后再显示,如下: | 当你拿到 <code>1.4000000000000001</code> 这样的数据要展示时,建议使用 <code>toPrecision</code> 凑整并 <code>parseFloat</code> 转成数字后再显示,如下: | ||
parseFloat(1.4000000000000001.toPrecision(12)) === 1.4 // True | |||
封装成方法就是: | 封装成方法就是: | ||
function strip(num, precision = 12) { | function strip(num, precision = 12) { | ||
第20行: | 第22行: | ||
=== 数据运算类 === | === 数据运算类 === | ||
对于运算类操作,如 <code>+-*/</code>,就不能使用 <code>toPrecision</code> 了。正确的做法是把小数转成整数后再运算。以加法为例: | 对于运算类操作,如 <code>+-*/</code>,就不能使用 <code>toPrecision</code> 了。正确的做法是把小数转成整数后再运算。以加法为例: | ||
/** | |||
* 精确加法 | |||
*/ | |||
function add(num1, num2) { | |||
const num1Digits = (num1.toString().split('.')[1] || '').length;'' | |||
const num2Digits = (num2.toString().split('.')[1] || '').length;'' | |||
const baseNum = Math.pow(10, Math.max(num1Digits, num2Digits)); | |||
return (num1 * baseNum + num2 * baseNum) / baseNum; | |||
} | |||
=== 别的解决方案 === | |||
还找到一个别的现成的JavaScript类库,例如 | |||
https://github.com/MikeMcl/decimal.js | |||
https://www.html.cn/archives/7340/comment-page-1 | |||
[[分类:Html]] |
2019年4月10日 (三) 21:34的最新版本
调试JavaScript代码的时候涉及了浮点数运算
出现了很奇怪的结果
> 5.1+2.55
> 7.6499999999999995
????????
祭出搜索引擎,获得文章
JavaScript 浮点数陷阱及解法 https://github.com/camsong/blog/issues/9
里面提到了两个解决方案
数据展示类
当你拿到 1.4000000000000001
这样的数据要展示时,建议使用 toPrecision
凑整并 parseFloat
转成数字后再显示,如下:
parseFloat(1.4000000000000001.toPrecision(12)) === 1.4 // True
封装成方法就是:
function strip(num, precision = 12) { return +parseFloat(num.toPrecision(precision)); }
为什么选择 12
做为默认精度?这是一个经验的选择,一般选12就能解决掉大部分0001和0009问题,而且大部分情况下也够用了,如果你需要更精确可以调高。
数据运算类
对于运算类操作,如 +-*/
,就不能使用 toPrecision
了。正确的做法是把小数转成整数后再运算。以加法为例:
/** * 精确加法 */ function add(num1, num2) { const num1Digits = (num1.toString().split('.')[1] || ).length; const num2Digits = (num2.toString().split('.')[1] || ).length; const baseNum = Math.pow(10, Math.max(num1Digits, num2Digits)); return (num1 * baseNum + num2 * baseNum) / baseNum; }
别的解决方案
还找到一个别的现成的JavaScript类库,例如
https://github.com/MikeMcl/decimal.js
https://www.html.cn/archives/7340/comment-page-1