float和double型,的底层实现是二进制的。十进制中的一个有限位数小数,转换成二进制就不一定是有限位数了,一旦位数超过的float和double型的位数宽度,就会出现“精度溢出”。所以float和double型是为了科学计算而设计的,并不适合精确的十进制计算,尤其不适合用来表示货币。
我以前也曾出货类似于为什么 2.0f - 1.9f 的结果不是 0.1f 之类的面试题。原因前面已经说了,其实不管什么语言,只要是标准的单精度浮点和双精度浮点类型的实现,就都存在此问题。VB.Net、C#甚至AS3中的Number型(从精度上看应该是Double)也都如此。
好在Java给我们准备了BigDecimal(C#中也可以通过引用java.math使用J#的BigDecimal)。但是BigDecimal是一个非常标准的类,因而对它的加减乘除等运算以及比较大小使用起来要比原生的数值类型要麻烦一些。(Java也不支持操作符重载)
再有一点,就是在跨语言协作时,序列化/反序列化时,其他语言往往没有相应的类型与Java的BigDecimal对应。(AS3就只能用String与之对应)
【Effective Java 学习笔记】系列连载专题请见:
http://tonylian.iteye.com/categories/64208