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三行,其余一行
(这玩意儿有个*用啊…