您的位置:首页 > Web前端 > JavaScript

关于JS浮点精度问题

2015-02-04 09:54 645 查看
在JS中 0.1 + 0.2 = 0.30000000000000004 而不是0.3

console.log((0.1).toString(2)) ====>0.0001100110011001100110011001100110011001100110011001101

console.log((1).toString(2)) ====> 1

这是因为js中的浮点数使用IEEE 754标准的双精度浮点数表示

IEEE双精度格式具有53位有效数字精度(包含符号号),并总共占用64位。

双精度二进制小数,使用64个比特存储。
1位
11位
52位
S(符号位),编号63
E(阶码位),编号62 ~52
M(小数位),编号51 ~ 0
0表示正,1表示负
−1022~+1023加上1023
任意
最高位63位是符号位,1表示该数为负,0表示该数为正;

62-52位,一共11位是指数位;

51-0位,一共52位是尾数位。

十进制0.1

=> 二进制0.00011001100110011…(循环0011) ====> 0.1 相当于 1/16+1/32+ 1/256 +1/512 ............

=>尾数为1.1001100110011001100…1100(共52位,除了小数点左边的1),指数为-4(二进制移码为00000000100),符号位为0

=> 计算机存储为:0 00000000100 10011001100110011…11001

=> 因为尾数最多52位,所以实际存储的值为0.00011001100110011001100110011001100110011001100110011001

而十进制0.2

=> 二进制0.0011001100110011…(循环0011)

=>尾数为1.1001100110011001100…1100(共52位,除了小数点左边的1),指数为-3(二进制移码为00000000011),符号位为0

=> 存储为:0 00000000011 10011001100110011…11001

因为尾数最多52位,所以实际存储的值为0.00110011001100110011001100110011001100110011001100110011

 那么两者相加得:

0.00011001100110011001100110011001100110011001100110011001

+ 0.00110011001100110011001100110011001100110011001100110011 (确认??)

= 0.01001100110011001100110011001100110011001100110011001100

转换成10进制之后得到:0.30000000000000004

解决方法

1 可以奖浮点数化为整数 0.1+0.2 =1+2/10 ; 相当于( a*10+b*10)/10

关于浮点数

浮点数格式使用科学计数法表示实数。科学计数法把数字表示为系数(coefficient)(也称为尾数(mantissa)),和指数 (exponent)两部分。

比如 3.684*10^2. 在十进制中,指数的基数为 10,并且表示小数点移动多少位以生成系数。每次小数点向前移动时,指数就递增;

每次小数点向后移动时,指数就递减。例如,25.92 可表示为 2.592 * 10^1,其中 2.592 是系数,值 10^1 是指数。必须把系数和指数相乘,才能得到原始的实数。

另外,如 0.00172 可表示为 1.72*10^-3,数字 1.72 必须和 10^-3 相乘才能获得原始值。

计算机系统使用二进制浮点数,这种格式使用二进制科学计数法的格式表示数值。数字按照二进制格式表示,那么系数和指数都是基于二进制的,而不是十进制,

例如 1.0101*2^2

在十进制里,像 0.159 这样的值,表示的是 0 + (1/10) + (5/100) + (9/1000)。

相同的原则也适用二进制。比如,1.0101 乘以 2^2 后,生成二进制值 101.01 ,这个值表示二进制整数 5,加上分数 (0/2) + (1/4) 。

这生成十进制值 5.25 。下表列出几个二进制小数以及它们对应的十进制值:
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: