float 大小为 32-bit
存储的结构:1位符号位,8位指数(幂),23位尾数
double 大小为 64-bit
存储的结构:1位符号位,11位指数(幂),52位尾数
float与double结构类似,下面以float为例子做分析:
1、通过程序的方式获取float的二进制表示:
public class FloatTest { public static void main(String[] args) { float f = 8; //因为int型与float型在内存中的长度相同,用floatToIntBits()可以把float中的二进制标示转为int型表示。类似double可转为long int i = Float.floatToIntBits(f); System.out.println(Integer.toBinaryString(i)); } }
2、通过计算的方式获取float的二进制表示:
以float f = 20014999 为例
1)20014999 的二进制为1001100010110011110010111
2)规格化后 1.001100010110011110010111*2^24
尾数为001100010110011110010111
此时24位,但float的尾数只有23位。四舍五入后为00110001011001111001100
3)幂为24+127 二进制为:10010111。
其中127为 float的偏移附加,double的偏移附加为1023。具体解释参照:IEEE 754 (二进制浮点数算术标准)
4)加上符号位0。 0表示正数,1表示负数
最后,内存中的表示为:0 10010111 00110001011001111001100
上面的过程中可以看出float精度丢失的原因。需要高精度,如金额的计算不能用浮点型,一般可用BigDecimal。
使用BigDecimal需要注意的一点是:BigDecimal 也有一些令人奇怪的行为。尤其在使用 equals() 方法来检测数值之间是否相等时要小心。 equals() 方法认为,两个表示同一个数但换算值不同(例如, 100.00 和 100.000 )的 BigDecimal 值是不相等的。然而, compareTo() 方法会认为这两个数是相等的,所以在从数值上比较两个 BigDecimal 值时,应该使用 compareTo() 而不是 equals() 。
3、float、double、long型 常量的表示问题。
float 型常量后面加F or f 如 3.14f
double 型常量后面加D or d 或者不加 3.14d or 3.14(默认为双精度)
long 型常量 加L or l
int 型常量 不加后缀
一般我们都不加这个后缀,其实是因为程序做了类型转换。
但当超出范围时需要注意。
如:
long L1 = 8888888888;//会报错,因为8888888888为int型常量,但超出了int的范围。
*花边知识:
1、计算机上表达实数有两中方法:定点表示(fixed-point)和浮点表示(floating-point)。
2、上面的提到的方法Float.floatToIntBits()的jdk 1.7的源码如下:
public static int floatToIntBits(float value) { int result = floatToRawIntBits(value); // Check for NaN based on values of bit fields, maximum // exponent and nonzero significand. if ( ((result & FloatConsts.EXP_BIT_MASK) == FloatConsts.EXP_BIT_MASK) && (result & FloatConsts.SIGNIF_BIT_MASK) != 0) result = 0x7fc00000; return result; }
其中的 floatToRawIntBits();方法的实现为:
public static native int floatToRawIntBits(float value);
这里用到native因为这个方法的实现需要操作内存,所以但在java无法实现,只能通过调用C语言来实现底层的操作。
3、前人研究:
java float double精度为什么会丢失?浅谈java的浮点数精度问题
http://blog.csdn.net/abing37/archive/2010/02/27/5332798.aspx
Java中的double类型数据存储探析
http://blog.csdn.net/softwater007/archive/2008/11/18/3330619.aspx
IEEE754 学习总结
http://www.pediy.com/bbshtml/BBS6/pediy6610.htm
使用浮点数和小数中的陷阱
http://www.360doc.com/content/07/0308/10/14474_388882.shtml
4.相关规范
IEEE754:http://babbage.cs.qc.edu/courses/cs341/IEEE-754references.html