dalao群讨论到浮点数标准的时候吐槽了一下JavaScript的浮点数精度问题,然后莫名发现了一些有意思的浏览器特点
先吐槽一下,居然有十进制的浮点数…我一直以为只有二进制的
在说到十进制浮点数和二进制浮点数的时候,提到了一个检测的方法:0.1+0.2==0.3… 因为二进制浮点数没办法正确表示这数字,所以总是不等的。这时候突然开始吐槽(黑)了一下js的精度问题,于是就观察了一些东西。
众所周知,2的幂不会是0结尾的… 然而Chrome里面2 ** 63的结果是9223372036854776000(正确应为9223372036854775808)。
但是这个肯定是js独有的坑:Math.pow(99, 99) != 99 ** 99
Math.pow(99, 99) == 99 ** 99
// false
3.697296376497263e+197 == Math.pow(99, 99)
// true
3.697296376497268e+197 == 99 ** 99
// true
(经过实际测试,发现这个问题不存在于Firefox/Edge/IE中:就是说,这是个Chrome独有的bug - 或者说是V8的。IE不存在这个问题是因为不支持ES7,所以没办法用**运算符…IE:今天我是流泪狗狗头
经过进一步的研究(把几种可能暴力组合后)发现,这个问题只出现于硬编码的计算当中(即99 ** 99),其余的方法(例如说var x = 99; x ** x这样都不会出现问题)
于是沙雕群友就在群里发了这样的代码:
try {
    if (Math.pow(99, 99) != 99 ** 99) console.log('Chrome');
    else if (99 ** 99 == 3.697296376497263e+197) console.log('Firefox');
    else if (99 ** 99 == 3.697296376497268e+197) console.log('Edge');
    else console.log('未知浏览器');
} catch (err) {
    console.log('你的浏览器不支持ES7'); // 说的就是你@IE
}
蛇精病的我突然开始好奇 还有什么别的骚操作可以检查浏览器环境吗… 根据经验,UA是个不怎么靠谱的方案,感觉各种被改… 貌似找js的运行时或环境里的神秘坑会有点用
很容易就找到了浏览器里的一个叫navigator的玩意儿… 虽然恕我直言,这里面一大半的玩意儿都会返回固定的(错误的)值。
| Chrome | Firefox | Edge | IE | Opera | Safari | |
|---|---|---|---|---|---|---|
| Math.pow(99, 99) | 3.697296376497263e+197 | 3.697296376497263e+197 | 3.697296376497268e+197 | 3.697296376497268e+197 | 3.697296376497263e+197 | 不明 | 
| 99 ** 99 | 3.697296376497268e+197 | 3.697296376497263e+197 | 3.697296376497268e+197 | ES7不支持 | 3.697296376497268e+197 | 不明 | 
| navigator.vendor | "Google Inc." | "" | "" | "" | 不明 | "Apple Computer, Inc."* | 
| navigator.oscpu | undefined | Windows NT 10.0; Win64; x64 | undefined | undefined | undefined | undefined | 
| navigator.platform | "Win32" | "Win32" | "Win32" | "Win32" | "Win32" | "Win32" | 
| navigator.product | "Gecko" | "Gecko" | "Gecko" | "Gecko" | "Gecko" | "Gecko" | 
| navigator.productSub | "20030107" | "20100101" | "20030107" | undefined | "20030107" | "20030107"* | 
| navigator.webdriver | undefined | true或false | true或false | true或false | 不明 | 不明 | 
| escape(Math.pow.toString()) | 一行 "function pow() { [native code] }" | 三行 "function pow() {\r\n    [native code]\r\n}" | 一行 "function pow() { [native code] }" | 五行 "\r\nfunction pow() {\r\n    [native code]\r\n}\r\n" | 一行 "function pow() { [native code] }" | 不明 | 
大致总结:
只有Firefox有navigator.oscpu
Chrome和Safari有navigator.vendor
Chrome的Math.pow(99, 99) != 99 ** 99,Firefox的计算结果以3结尾,Edge的结果以8结尾
方法toString后IE为五行,Firefox三行,其余一行
(这玩意儿有个*用啊…