实数表示
float和double为什么能表示的范围大?为什么会失真?
float能表示有效位数为6-7位,double有效位数为15-16位(负值取值范围为 -1.7976E+308 到 -4.94065645841246544E-324,正值取值范围为 4.94065645841246544E-324 到 1.797693E+308)。
float占4个字节,有32位:分别是符号位S(1位),指数位E(8位),尾数M(23位)。
比如123.6,写成二进制是10100101.0100=1.01001010100x2^7,存储过程:
首先符号位S,0表示正数,1表示负数。S=0;
然后算出指数位E,这里指数为:e=7=0000 0111,根据IEEE754标准要求,E=e+127;即:E=7+127=134=1000 0110;
再写出尾数M,即:M=0100 1010 1000 0000 0000 000;
M(23位)最大可以表示7位数,因此float有效位为(精确到)7位,可以表示的负值取值范围为-2128~-2104,正值取值范围为2104~2108。double同理。
所以可以看到,虽然float和double可以表示的位数很大,但是牺牲了精确度。
java如何比较float或double的大小:
- 最常用:相减在某个范围内,如(double1-double2<=1e-6)
- 转成字符串比较,但只适用于精度相同的
- 使用sun提供的Double.doubleToLongBits()方法
- 商业计算最好用BigDecimal。而且尽量用其字符串构造函数,比如BigDecimal("0.3")而不是BigDecimal(0.3)