JS位运算问题
0.1+0.2的问题
JavaScript 深入之浮点数精度 · Issue #155 · mqyqingfeng/Blog
js如何表示小数
那如果是 0.75 用二进制表示呢?同理应该是:
0.75 = a * 2^-1 + b * 2^-2 + c * 2^-3 + d * 2^-4 + ...
因为使用的是二进制,这里的 abcd……的值的要么是 0 要么是 1。
0.1 = a * 2^-1 + b * 2^-2 + c * 2^-3 + d * 2^-4 + ...
0 + 0.2 = a * 2^0 + b * 2^-1 + c * 2^-2 + ... (a = 0)
0 + 0.4 = b * 2^0 + c * 2^-1 + d * 2^-2 + ... (b = 0)
0 + 0.8 = c * 2^0 + d * 2^-1 + e * 2^-2 + ... (c = 0)
1 + 0.6 = d * 2^0 + e * 2^-1 + f * 2^-2 + ... (d = 1)
1 + 0.2 = e * 2^0 + f * 2^-1 + g * 2^-2 + ... (e = 1)
0 + 0.4 = f * 2^0 + g * 2^-1 + h * 2^-2 + ... (f = 0)
0 + 0.8 = g * 2^0 + h * 2^-1 + i * 2^-2 + ... (g = 0)
1 + 0.6 = h * 2^0 + i * 2^-1 + j * 2^-2 + ... (h = 1)
....
然后你就会发现,这个计算在不停的循环,所以 0.1 用二进制表示就是 0.00011001100110011……
一些进制转换
// 十进制转二进制
parseFloat(0.1).toString(2);
=> "0.0001100110011001100110011001100110011001100110011001101"
// 二进制转十进制
parseInt(1100100,2)
=> 100
// 以指定的精度返回该数值对象的字符串表示
(0.1 + 0.2).toPrecision(21)
=> "0.300000000000000044409"
(0.3).toPrecision(21)
=> "0.299999999999999988898"
技巧
使用&, >>, |来完成rgb值和16进制颜色值之间的转换
/**
* 16进制颜色值转RGB
* @param {String} hex 16进制颜色字符串
* @return {String} RGB颜色字符串
*/
function hexToRGB(hex) {
var hexx = hex.replace('#', '0x')
var r = hexx >> 16
var g = hexx >> 8 & 0xff
var b = hexx & 0xff
return `rgb(${r}, ${g}, ${b})`
}
/**
* RGB颜色转16进制颜色
* @param {String} rgb RGB进制颜色字符串
* @return {String} 16进制颜色字符串
*/
function RGBToHex(rgb) {
var rgbArr = rgb.split(/[^\d]+/)
var color = rgbArr[1]<<16 | rgbArr[2]<<8 | rgbArr[3]
return '#'+ color.toString(16)
}
// -------------------------------------------------
hexToRGB('#ffffff') // 'rgb(255,255,255)'
RGBToHex('rgb(255,255,255)') // '#ffffff'