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

Js 中 parseInt(0.0000008) 等于 8

  •  
  •   oska117 · 2018-03-28 22:18:34 +08:00 · 4061 次点击
    这是一个创建于 2437 天前的主题,其中的信息可能已经有所发展或是发生改变。

    今天遇到个问题,发现 js 中一些注意的地方

    parseInt(0.000008) 结果为 0

    parseInt(0.0000008) 结果为 8

    parseInt("0.0000008") 结果为 0

    第二个感觉好奇怪,就在网上搜, 结果在阮一峰的《 js 标准参考手册》发现

    “对于那些会自动转为科学计数法的数字,parseInt 会将科学计数法的表示方法视为字符串,因此导致一些奇怪的结果。”

    也就是说,0.0000008 会先自动转换为 科学计数法 8e-7, 然后自动转为字符串 “ 8e-7 ”,结果就是 8 了

    12 条回复    2018-03-30 18:20:55 +08:00
    songz
        1
    songz  
       2018-03-28 22:44:21 +08:00
    先套个 floor 就没有意外了
    rock_cloud
        2
    rock_cloud  
       2018-03-28 22:50:54 +08:00
    怎么感觉像是 bug。。。
    huweitxdy
        3
    huweitxdy  
       2018-03-28 23:03:26 +08:00
    ecma 规范里似乎就是这么写的。。。
    owwlo
        4
    owwlo  
       2018-03-28 23:09:24 +08:00
    踩坑留念
    mchl
        5
    mchl  
       2018-03-28 23:13:39 +08:00 via iPhone
    第一反应是试一下 parseInt(Number(0.0000008) )
    oska117
        6
    oska117  
    OP
       2018-03-28 23:25:12 +08:00 via Android
    还有 NaN !==NaN , 也就是 NaN 不等于它自身
    zybzzc
        7
    zybzzc  
       2018-03-28 23:47:32 +08:00 via Android
    yyfearth
        8
    yyfearth  
       2018-03-29 09:01:07 +08:00   ❤️ 1
    @mchl @songz 没区别的 因为 Number(0.0000008) === 0.0000008
    parseInt(string) 所以都会被转换成 string
    而 String(0.0000008) === '8e-7'
    parseInt 不支持科学计数
    所以 parseInt(0.0000008) === parseInt('8e-7') === 8

    而 parseFloat 支持科学计数 所以没问题
    parseFloat(0.0000008) === parseFloat('8e-7') === 8e-7 === 0.0000008
    songz
        9
    songz  
       2018-03-29 09:03:17 +08:00   ❤️ 1
    parseInt(8e-6)
    0
    parseInt(8e-7)
    8

    为什么-6 就是 0 呢?
    whosesmile
        10
    whosesmile  
       2018-03-29 10:01:24 +08:00   ❤️ 2
    @songz 查了下文档,yyfearth 漏说了一句:
    parseInt 和 parseFloat 接受的参数是 string,如果参数不是 string,那么会先转换为 string.
    这和我们(包括我...)想象的不一样,以为接受的参数可以是数字

    所以对 8e-6 的转换的流程是: parseInt(8e-6) === parseInt(String(8e-6)) === parseInt("0.000008") === 0
    所以对 8e-7 的转换的流程是: parseInt(8e-7) === parseInt(String(8e-7)) === parseInt("8e-7") === 8

    你要是问为什么 String(8e-6)和 String(8e-7)的结果不一样(因为我也奇怪),然后定位到 ECMA 的文档规范,没看懂,但是这就是规范规定的:根据数字范围的不同,转换成字符串的结果是不一样的。就这么任性。。。

    我猜想这么设计的原因是 js 中所有的数字只有一种类型:Number,实际内存的表达式通过 float 方式存储的,这样如果数字的长度过大,转换为字符串就会非常长,所以才这么设计出了转换规则。
    codehz
        11
    codehz  
       2018-03-29 11:57:00 +08:00
    @oska117 #6 NaN 这个是设计(而且符合浮点数的标准
    还有正 0 和负 0 呢!
    Object.is(0, -0) //false
    另外 NaN 也可以用 Object.is 来比较(
    Justin13
        12
    Justin13  
       2018-03-30 18:20:55 +08:00 via Android
    差的那一位就是小数和科学计数法的边界。7 位及以上用科学计数法,6 位及以下依旧是小数,所以结果不同。。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4810 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 79ms · UTC 09:54 · PVG 17:54 · LAX 01:54 · JFK 04:54
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.