[TOC]

解法1

在Effective java中,第48条中提到如果需要精确的答案,请避免使用float和double,float和double尤其不适合用于货币计算。替代方案是使用BigDecimal或int,long。如果数值范围没有超过9位,可以选择int,不超过18位可能选择long,超过18位对性能不是很关注就可以选择BigDecimal。

解法2

对于有些希望精确计算的结果,可以使用份数来表。在编程之美2.6中讨论了怎么用分数来表达一个小数。

所有的小数都尅分解为一个整数和一个纯小数之和,这里不妨只考虑大于0,小于1的纯小数,且暂时不考虑分子和分母的约分。

  • 对于有限小数 X= 0.a1a2...an来说,X = a1a2a3...an/10^n;

  • 对于无线循环小数来说,我们可以做如下转换

    $$ X=0.a_1a_2...a_n(b_1b_2...b_m)\\ =>10^n*X=a_1a_2...a_n(b_1b_2...b_m)\\ =>10^n*X=a_1a_2...a_n+0.(b_1b_2...b_m)\\ =>X=\frac{a_1a_2...a_n+0.(b_1b_2...b_m)}{10^n} $$

    对于整数部分a1a2...an,不需要做额外处理,只需要把小数部分转换为分数再加上这个部分即可,对于后面的无限循环部分,可以采用如下方式处理

    令Y=0.(b1b2...bm),那么

    $$ 10^m*y =b_1b_2...b_m.(b_1b_2...b_m)\\ =>10^m*y=b_1b_2...b_m+0.(b_1b_2...b_m)\\ =>10^m*y=b_1b_2...b_m+y\\ =>y=\frac{b_1b_2...b_m}{10^m-1} $$

    将Y带入前面的公式即得

    $$ <Empty \space Math \space Block> $$

    $$ X=\frac{(a_1a_2...a_n)+y}{10^n}\\ =\frac{(a_1a_2...a_n)+\frac{b_1b_2...b_m}{10^m-1}}{10^n}\\ =\frac{(a_1a_2...a_n)*(10^m-1)+(b_1b_2...b_m)}{10^n*(10^m-1)} $$


掌握了推导的公式,一切就变得简单点了。

关于Markdown的数学公式参考可以看这里