OurJS


OurJS-我们的JS, 我们的技术-IT文摘; 专注JS相关领域;
我们热爱编程, 我们热爱技术;我们是高大上, 有品味的码农;

欢迎您订阅我们的技术周刊


我们会向您分享我们精心收集整理的,最新的行业资讯,技术动态,外文翻译,热点文章;
我们使用第三方邮件列表向您推送,我们不保存您的任何个人资料,注重您的隐私,您可以随时退订,

欢迎分享您的观点,经验,技巧,心得

让我们一起找寻程序员的快乐,探索技术, 发现IT人生的乐趣;


本网站使用缓存技术每次加载仅需很小流量, 可在手机中流畅浏览;
如果您发现任何BUG,请即时告知我们: ourjs(at)ourjs.com

JavaScript的设计缺陷?浮点运算:0.1 + 0.2 != 0.3


分享到
分类 JS学习   关键字 JavaScript   发布 kris  1416188801307
注意 转载须保留原文链接,译文链接,作者译者等信息。  
在Stackoverflow上面有这样一个提问

浮点运算的问题


在JavaScript中进行纯小数运算偶尔会得到不正确的结果:

> 0.1 + 0.2 == 0.3
false
> 0.1 + 0.2
0.30000000000000004

很多人马上就开始认为JavaScript设计的不成熟,设计上有缺陷。

实际上这并不是JavaScript仅有的问题,C/C++/Java甚至Matlab都有这个问题,参见: why 0.3-0.2-0.1 not equal to zero

 这只是JavaScript遵循IEEE 754标准所产生的必然结果。IEEE 754标准中的浮点数并不能精确地表达小数(比如说0.1),

  • 你需要足够的内存来保留5个数字
  • 你需要使用一个取值范围来确保精度。

在硬件层面,除法是转换成乖法来表示的,比如: Z = X/Y 会变成 Z = X * (1/Y);

JavaScript中的小数采用的是双精度(64位)表示的,由三部分组成: 符 + 阶码 + 尾数,在十进制中的 1/10,在十进制中可以简单写为 0.1 ,但在二进制中,他得写成:0.0001100110011001100110011001100110011001100110011001…..(后面全是 1001 循环)。因为浮点数只有52位有效数字,从第53位开始,就舍入了。这样就造成了“浮点数精度损失”问题。 (参考: 出处1出处2

所以你在处理小数运算时要非常小心。


怎么解决


就像标准中提到的,我们可以采用一个精确范围来比较是否相等

x = 0.2;
y = 0.3;
equal = (Math.abs(x - y) < 0.000001)


第二种方法是使用JavaScript内置的函数toPrecision或toFixed来保留一定的精度:

(0.1 + 0.2).toPrecision(10) == 0.3
> true
(0.1 + 0.2).toFixed(10) == 0.3
> true
社区评论 ( Beta版 )
  • #0 夏云示 1416359592354

    醉了!

  • #1 孔四当 1416383516579

    果然等于0.30000000000000004

  • #2 bawanag 1416390416966

    这bug有点吓人啊,以后写程序小心小心

  • #3 kris 1416391787193

    @bawanag #2

    这种问题在实际中遇到的概率非常非常小,通常只要计算中有一个为含整数部的数字即可避免出现纯双精度小数的情况。

    如:

    0.1 + 0.2 + 1.0
    > 1.3
    
  • #4 龚半半 1416448931425

    public static void main(String[] args) { System.out.println(0.1+0.2); }

    0.30000000000000004

  • #5 justjavac 1416789211312
  • #6 廉迈田 1417760161411

    good

  • #7 毕出乡 1418705404645

    人收到复古风的官方个德国法国代购大股东

  • #8 TylerTemp 1418813849691

    @bawanag #2

    这不是Bug. 使用二进制必然存在的问题.

  • #9 华世丰 1439576675639

    @bawanag #2

    sb程序员才会认为这是bug.

  • #10 池片死 1466131624197

    @华世丰 #9

    别管什么原因导致的,是不是必然,计算出来的东西和预计的东西不一样就是BUG。SB才会认为错的东西是对的。

  • #11 韦虫记 1467021921221

    (0.1 + 0.2).toFixed(10) == 0.3是true 但(0.1 + 0.2).toFixed(10) === 0.3是false

  • #12 俞问州 1474363180669

    1 = 3*(1/3) = 3*0.33333333333 = 0.99999999999

  • #13 姜七世 1476264539312

    @池片死 #10

    0.1 + 0.2 結果是 0.30000000000000004 是「正確」的沒錯啊。

    JS 語言定義就是如此,當只寫 0.1 的時候 JS 預設採用 IEEE 754 來描述你的 0.1,在這個條件下 0.1 + 0.2 的結果必然就是 0.30000000000000004。

    如果你預計的答案是 0.3,那代表你用錯方法,而不是該語言的 bug。

  • #14 康汁丁 1481462193449

    ...

OnceDoc 您自己的企业内容管理系统——文档、流程、知识库、报表、网盘All In One

访问404页面,寻找丢失儿童
 热门文章 - 分享最多
  1. Nginx的大计划:将原生支持JavaScript
  2. NodeJS会是昙花一现吗?
  3. Google收购Firebase,Fire加入谷歌云平台
  4. Go语言实例教程基础语法篇(一)
  5. 理解JavaScript中的事件路由冒泡过程及委托代理机制
  6. SpiderMonkey的JavaScript引擎[Firefox]性能超越V8[Chrome]
  7. Debug调试Node.JS:我们是如何定位内存泄漏和无限循环的
  8. Angular.JS出了什么问题?
  9. 基于HTML5和JavaScript实现的Winamp MP3播放器
  10. 15个最好用的Node.JS后端框架
  11. AirJD-简单好用的免费建站工具

 相关阅读 - JS学习
  1. Debug调试Node.JS:我们是如何定位内存泄漏和无限循环的
  2. 理解JavaScript中的事件路由冒泡过程及委托代理机制
  3. 用JavaScript制作HTML5动画基础
  4. Node.js 包教不包会
  5. 使用Javascript开发OS X应用程序
  6. Node程序中的设计模式
  7. 制作canvas游戏
  8. 5个经典的前端面试问题
  9. 拿什么守护你的Node.JS进程: Node出错崩溃了怎么办?
  10. 合并JavaScript数组的N种方法

 关键字 - JavaScript
  1. 7个最新的实用性 JavaScript MV*框架
  2. 抛弃jQuery,深入原生的JavaScript
  3. WebPack:更优秀的模块依赖管理工具,及require.js的缺陷
  4. 5个现在就该使用的数组Array方法: indexOf/filter/forEach/map/reduce详解
  5. 用HTML5原生实现拖放或排序
  6. 少年,不要滥用箭头函数啊:JS中lambda表达式的优缺点和使用场景
  7. 用原生HTML5控件实现输入框自动提示(下拉列表补全)功能
  8. OnceIO模块开发:模块注册、模块路由、静态文件重定向以及如何开发与设计一个功能扩展模块
  9. JavaScript中NaN的秘密
  10. 从一行CSS调试代码中学到的JavaScript知识

 欢迎订阅 - 技术周刊

我们热爱编程, 我们热爱技术; 我们是高端, 大气, 上档次, 有品味, 时刻需要和国际接轨的码农; 欢迎您订阅我们的技术周刊; 您只需要在右上角输入您的邮箱即可; 我们注重您的隐私,您可以随时退订.
加入我们吧! 让我们一起找寻码农的快乐,探索技术, 发现IT人生的乐趣;


 关注我们

我们的微信公众号: ourjs-com
打开微信扫一扫即可关注我们:
IT文摘-程序员(码农)技术周刊

ourjs官方微信号