分享

不要用float和double来进行精确的小数计算 - Ye Yiliang‘s Blog - BlogJava

 ShangShujie 2006-09-14

不要用floatdouble来进行精确的小数计算

 

什么?难道它们不就是为了小数计算而生的么?在我看到 effective java item31 的时候,发出了这个孤陋寡闻的疑问。

 

知其然:

为什么说不能用 float double 来进行精确小数计算呢?

试试执行这样的语句:

System.out.println( 1.03   -  . 42 ); // 答案是0.6100000000000001 !

System.out.println(
1.00   -   9 * . 10 ); // 答案是0.09999999999999995 !

你会发现结果和你的小学数学课程有冲突。

 

知其所以然

之所以出现这样的奇怪答案,是因为 float double 不能精确的表达 0.1 ,或者任何 10 的负 n 次方。他们是设计来进行科学和工程上的计算,提供精确的近似值的。它们在涉及金融方面的计算则是不在行的。因为金融方面要求绝对的精确。

 

解决方法

BigDecimal int 或者 long

 

 

BigDecimal bd  =   new  BigDecimal( " 1.00 " );

 

 

把所有牵涉到的小数都以这种方式转变为 BigDecimal 对象,然后用它提供的方法进行计算。

你就得到了精确的计算结果,随之而来有两个小缺点,一个。。。很显然,就是比直接用原始类型要麻烦,也不能用 +,-,*,/ 这些直观的符号了;第二个就是速度会慢一点,如果不是用于大量的循环之中,则不是那么要紧。不过,你也同时得到了一个好处, BigDecimal 类还带了丰富的舍入方法,也是不错的。

如果小数位本身不长,则可以用 int 或者 long 来替代,我想你明白这个方法是什么意思的。在速度必须很快的位置,你又不介意自己看着小数点位,这个还是可用的,但如果数字本身超过了 18 位,就只能用 BigDecimal 了。

 

Wednesday, September 13, 2006

Don’t use float and double when exact answers are required

 

What? Aren’t calculating decimal are what they are design for? I made such an ignorant question when I first read effective java-item31.

 

The phenomenon:

Why we can’t use float and double to calculate decimal when exact results are required?

Try the following statements:

 

System.out.println( 1.03   -  . 42 ); // the answer is 0.6100000000000001 !

System.out.println(
1.00   -   9 * . 10 ); // the answer is 0.09999999999999995 !

 

You will find the answers are not agree with what you have learned in primary school.

 

The reason:

It is all because float and double can not represent exactly 0.1, or any other negative power of ten. They are designed for scientific and engineering calculation which demands accurate approximation. And they are ill-suited for monetary calculations.

 

The solution:

Use BigDecimal, int or long instead.

 

 

BigDecimal bd  =   new  BigDecimal( " 1.00 " );

 

 

Transfer all decimal numbers involved in the calcution into BigDecimal objects as above, and then use them to calcute for a exact result, following with two disadvantages, the first, obviously, less convenient than using primitive types, all notations like +,-,*,/ can not be applied neither; the second, it will be slower, which can be ignored if it was not used in a heavily repeated loop. But you also get one merit which comes from the fact that BigDecimal carrys quite a lot of rounding methods.

If the quantity is not big, you can use int or long instead, you surely understand how to implement the idea. In performance critical section, and you don’t mind keeping track the of the decimal point yourself, this is feasible. But you have not choice if the quantity is over 18 digits, only BigDecimal is available.

posted on 2006-09-13 19:23 Ye Yiliang 阅读(461) 评论(3)  编辑 收藏 收藏至365Key 所属分类: Java

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多