V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
jason19659
V2EX  ›  程序员

99999999999999999999 === 100000000000000000000?

  •  
  •   jason19659 ·
    jason19659 · 2020-02-21 00:26:16 +08:00 · 4300 次点击
    这是一个创建于 645 天前的主题,其中的信息可能已经有所发展或是发生改变。

    99999999999999999999 === 100000000000000000000

    true

    谁能解释下

    第 1 条附言  ·  2020-02-21 01:11:26 +08:00
    typeof 99999999999999999999
    "number"
    22 条回复    2020-02-22 14:39:54 +08:00
    cmdOptionKana
        1
    cmdOptionKana   2020-02-21 00:33:56 +08:00
    一个提示:Javascript 没有整数,只有浮点数
    huihuimoe
        2
    huihuimoe   2020-02-21 00:45:18 +08:00 via Android   ❤️ 3
    @cmdOptionKana 有整数的,现在 bigint 已经在浏览器普及了。
    只要在数字后加个 n 就可以
    譬如 99999999999999999999n === 100000000000000000000n
    > false
    huihuimoe
        3
    huihuimoe   2020-02-21 00:48:36 +08:00 via Android
    至于楼主说的这个问题是编程经典问题,详细的内容可以搜索下 0.1+0.2 问题
    https://medium.com/better-programming/99432310d476
    Tink
        4
    Tink   2020-02-21 00:57:29 +08:00 via iPhone
    老问题了,搜一下
    luob
        5
    luob   2020-02-21 01:06:54 +08:00 via iPhone
    浮点数判断大小宜用减法
    cmdOptionKana
        6
    cmdOptionKana   2020-02-21 01:08:30 +08:00
    @huihuimoe 这种整数其实是个 object 了,不是基础数据类型,比如这种整数用于 JSON.stringify() 是会报错的。
    azh7138m
        7
    azh7138m   2020-02-21 01:14:09 +08:00 via Android   ❤️ 1
    @cmdOptionKana 不是
    它的类型就是 BigInt
    报错是标准要求
    https://tc39.es/proposal-bigint/#sec-serializejsonproperty
    azh7138m
        8
    azh7138m   2020-02-21 01:18:29 +08:00 via Android
    v8 用的 double 来存储 number
    数字已经过了 MAX_SAFE_INTEGER
    那其实就是楼上说的,这其实是个浮点数的比较(
    huihuimoe
        9
    huihuimoe   2020-02-21 01:44:44 +08:00 via Android
    typeof 99999999999999999999 === typeof 0.1
    > true
    lxk11153
        10
    lxk11153   2020-02-21 02:04:10 +08:00   ❤️ 2
    1. ECMAScript 将数字标准化为 64 位浮点值,也称为双精度浮点或 Float64。但是,这并不意味着 JavaScript 引擎总是以 Float64 的形式存储数字 —— 这么做会很低效。引擎会选择其它的内部表现形式,除非观测到的行为完全匹配 Float64。see: https://zhuanlan.zhihu.com/p/85836269

    2. https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER

    3. 0.1 +0.2===0.30000000000000004
    https://segmentfault.com/a/1190000011902474
    beginor
        11
    beginor   2020-02-21 03:18:19 +08:00 via Android
    搭车问一下,如果 json 中包含这些数字该怎么处理比较好?除了转成字符串
    tsohgdivil
        12
    tsohgdivil   2020-02-21 03:49:08 +08:00 via iPhone   ❤️ 21
    Mutoo
        13
    Mutoo   2020-02-21 05:51:38 +08:00
    kerr92
        14
    kerr92   2020-02-21 07:51:48 +08:00   ❤️ 1
    超出 [Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER],也就是 [-9007199254740991, 9007199254740991] 区间的数值,请用字符串或者 BigInt 表示。
    lxk11153
        15
    lxk11153   2020-02-21 09:10:57 +08:00
    @tsohgdivil #12 https://github.com/BonsaiDen/JavaScript-Garden
    A collection of documentation about the most quirky parts of the JavaScript language.
    ps: 里面的一些已在 es6 里改进,比如 for-of, let 等。see https://es6.ruanyifeng.com/
    mokevip
        17
    mokevip   2020-02-21 10:00:20 +08:00
    @tsohgdivil 当表情包收了(滑稽)
    xiangyuecn
        18
    xiangyuecn   2020-02-21 10:04:31 +08:00
    Number.MAX_SAFE_INTEGER=9007199254740991,这是 js 最大能精确表达的整数,你的那 n 个 9 的已经溢出了,js 不能准确表达这种大整数。据说现在有 BigInt,但是没用过。

    ps:这个跟浮点数 0.1+0.2 这个问题没有一毛钱关系
    drydiy
        19
    drydiy   2020-02-21 10:21:25 +08:00
    首先,目前 js 的数字类型有两种:Number、BigInt。其中 bigint 是后面加 n,不讨论,可以看下相关知识。
    number 类型都是双精度浮点型。
    1、2^53 - 1
    双精度浮点数能保存最大的“安全整数” 2^53 - 1,9007199254740991 为以下:
    parseInt("11111111111111111111111111111111111111111111111111111",2) // 9007199254740991
    双精度浮点数二进制存储形式:
    sign 位 exponent 位 franction 位 52 位 隐藏位 1
    0 10000110011 11111111111111111111111111111111111111111111111111111 1
    2、2^53
    当存储 9007199254740992(2^53) 为:
    parseInt("100000000000000000000000000000000000000000000000000000",2)
    双精度浮点数二进制存储形式:
    sign 位 exponent 位 franction 位 52 位 隐藏位 1
    0 10000110100 0000000000000000000000000000000000000000000000000000 1
    3、结论:
    从第 2^53 位开始,超出位被舍弃,这个时候,2^53+1===2^53。再过 N 个值,会出现每 4 个值里面都有 3 个值不精确;再过 M 个值,会出现每 2^K 个值里有 2^K-1 个值不精确;以此类推……
    额外:这里尾数是 52 位,但是最大安全整数是 2^53 - 1,这个 53 是因为用上了隐藏位。

    顺便说下 0.1+0.2 !== 0.3 的提示:计算机存储小数也是通过二进制存储,导致 2 的 n 次幂无法精确表示所有小数。

    最后,推荐下我总结的文章: https://www.yuque.com/dixdiydiz/qdjs/number
    lazzyboy
        20
    lazzyboy   2020-02-21 16:13:57 +08:00
    @tsohgdivil 请问你是怎么上传图片的,我记得 V2EX 没有图床啊

    ipixeloldc
        21
    ipixeloldc   2020-02-21 20:32:09 +08:00 via iPhone
    ArtsXiaoLu
        22
    ArtsXiaoLu   2020-02-22 14:39:54 +08:00
    这是个数学和天文知识,在 U2B 站上的视频上看过,具体忘了,好像是爱因斯坦说的
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2213 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 36ms · UTC 05:13 · PVG 13:13 · LAX 21:13 · JFK 00:13
    ♥ Do have faith in what you're doing.