建议22:用整数类型处理货币.

 public class Client {
public static void main(String[] args) {
System.out.println("10-9.5 = " + (10 - 9.5));
System.out.println("10-9.6 = " + (10 - 9.6));
}
}

运行结果:

 10-9.5 = 0.5
10-9.6 = 0.40000000000000036

奇怪了,为什么10-9.6输出结果不是0.4呢?
这是因为浮点数特性所决定的,它有可能(注意是有可能)是不准确的,而是无限接近准确值,但不能完全准确。至于它为什么会有这个特性,这是由于浮点数的存储规则所决定的,具体啥,就不深究了。

0.4这个十进制小数如何转换成二进制的小数,使用"乘2取整,顺序排列"法(不懂,这就没招了,太基础了.....),我们发现0.4不能使用二进制准确的表示,在二进制数的世界里它是一个无限循环的小数,也就是说,"展示"都不能"展示",更别说在内存中存储了.

浮点数的存储包括三部分:符号位,指数位,尾数.具体不在介绍.

可以这样理解,在十进制的世界里没有办法准确表示1/3,那在二进制世界里当然也无法准确表示1/5,在二进制的世界里1/5是一个无限循环的小数.

知道小数是如何转换为二进制就OK了,比如0.5,我们知道它的二进制数是:0.1;而0.4转换为二进制就难了, 是个无限循环的东东,
0.0110 0110 0110 ……(0110为循环节)。而计算机它只认识0和1,即0.4在转换时就失真了, 可想而知,输出结果多了一段小尾巴也不足为奇了,它只是为了达到无限接近准确值这个原则而已。

以后遇到这种对数据精度要求比较严格的数据处理时,我们应该如何去避免这类问题的发生?

对结果取整不就对了吗?

 public class Client {
public static void main(String[] args) {
NumberFormat f = new DecimalFormat("#.##");
System.out.println(f.format(10.00-9.60));
}
}

运行结果:打印出0.4

看似解决了问题,但是隐藏了一个很深的问题,金融行业的计算方法,会计系统一般记录小数点后的4位小数,但是在汇总,展现,报表中,则只记录小数点后的2位小数,如果使用浮点数来计算货币,想想看,在大批量的加减乘除后结果会有多大的差距.

会计系统要的就是准确.解决这个问题有两种方案:
第一种方案:
先乘以10的n次方化成整数参与运算,计算后,再除以10的n次方缩小回去。

这样处理是计算简单,准确,在 一般的非金融行业(如零售行业)应用比较多,此方法还会应用于某些POS机,它们的输入和输出全部是整数,那运算就更简单.
第二种方案:
我们应该想到java师祖们早已发现这个问题,并为我们提供类来解决这类问题,它就是BigDecimal类

BigDecimal是专门为弥补浮点数无法精确计算的缺憾而设计的类.而且它本身也提供了加减乘除的常用数学算法,特别是与数据库Decimal类型的字段映射时,BigDecimal是最优的解决方案.
具体使用参考如下网站:

http://blog.csdn.net/fenglibing/article/details/1765187

[改善Java代码]用整数类型处理货币的更多相关文章

  1. [改善Java代码]避开基本类型数组转换列表陷阱

    开发中经常用到Arrays和Collections这两个工具类. 在数组和列表之间进行切换.非常方便.但是也会遇到一些问题. 看代码: import java.util.Arrays; import ...

  2. [改善Java代码]提防包装类型的null值

    建议26: 提防包装类型的null值 我们知道Java引入包装类型(Wrapper Types)是为了解决基本类型的实例化问题,以便让一个基本类型也能参与到面向对象的编程世界中.而在Java 5中泛型 ...

  3. [改善Java代码]不要让类型默默转换

    建议23:不要让类型默默转换 public class Client { // 光速是30万公里/秒,常量 public static final int LIGHT_SPEED = 30 * 100 ...

  4. [改善Java代码] 谨慎包装类型的大小比较

    建议27:谨慎包装类型的大小比较 基本数据类型比较大小木有问题,不过其对应的包装类型大小比较就需要注意了.看如下代码: public class Client { public static void ...

  5. [改善Java代码]强制声明泛型的实际类型

    Arrays工具类有一个方法asList可以把一个变长参数或数组变成列表,但是它有一个缺点:它所生成的List长度是不可改变的,而这在我们的项目开发中很不方便. import java.util.Ar ...

  6. [改善Java代码]易变业务使用脚本语言编写

    建议16: 易变业务使用脚本语言编写 Java世界一直在遭受着异种语言的入侵,比如PHP.Ruby.Groovy.JavaScript等,这些“入侵者”都有一个共同特征:全是同一类语言—脚本语言,它们 ...

  7. [改善Java代码]数组的真实类型必须是泛型类型的子类型

    List接口的toArray方法可以把一个结合转化为数组,但是使用不方便,toArray()方法返回的是一个Object数组,所以需要自行转变. toArray(T[] a)虽然返回的是T类型的数组, ...

  8. [改善Java代码]Java的泛型是类型擦除的

    泛型可以减少强制类型的转换,可规范集合的元素类型,还可以提高代码的安全性和可读性,正是因为有了这些优点,自从Java引入泛型之后,项目的编码规则上便多了一条,优先使用泛型. Java泛型(Generi ...

  9. [改善Java代码]在equals中使用getClass进行类型判断

    建议47: 在equals中使用getClass进行类型判断 本节我们继续讨论覆写equals的问题.这次我们编写一个员工Employee类继承Person类,这很正常,员工也是人嘛,而且在JEE中J ...

随机推荐

  1. 给 TTreeView 添加复选框

    //1.引用单元 uses Commctrl ; //2.定义私有过程 procedure tvToggleCheckbox(TreeView: TTreeView;Node: TTreeNode;i ...

  2. codeforces 625C K-special Tables

    C. K-special Tables time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  3. 创建类模式(一):工厂方法(Factory Method)

    定义 此模式的核心精神是封装类中不变的部分,提取其中个性化善变的部分为独立类,通过依赖注入以达到解耦.复用和方便后期维护拓展的目的. 定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中.核心 ...

  4. RIA(富客户端)发展态势

    在过去的两到三年中,Web开发人员一直是想构建一种比传统HTML更丰富的客户端:这是一个用户接口,它比用HTML能实现的接口更加健壮.反应更加灵敏和更具有令人感兴趣的可视化特性.RIA技术的出现允许我 ...

  5. IE 、Firefox、Chrome 浏览器在 F12 控制台下切换至不同框架介绍

    有不少网页的页面,还在使用 iframe 标签,而此时,相当于页面有两个 window 对象,一个为当前页面 window ,另一个则为 iframe 页面下的 window .因为,有时候需要在 c ...

  6. TFS代码签入指导

    1. 如果文件没有被放入到TFS中, 那么它是不存在的. 这一点是最好被理解的, 如果你的代码没有被签入到代码管理中,那么就不可能被团队的其他人获取的得到. 具体如何将文件纳入到TFS中请参考 Pla ...

  7. 学习linux必备服务器VPS

    有很多和老沙一样喜欢linux或者喜欢架设服务器的朋友,因为没有linux环境在本机弄个虚拟机说实话很卡很不方便.老沙今天给大家推荐一款国外VPS,比这国内的云服务器便宜的太多了,年付19.99美元. ...

  8. java对象转JSON JS取JSON数据

    JsonConfig config = new JsonConfig(); config.setJsonPropertyFilter(new PropertyFilter() { @Override ...

  9. 继承虚函数浅谈 c++ 类,继承类,有虚函数的类,虚拟继承的类的内存布局,使用vs2010打印布局结果。

    本文笔者在青岛逛街的时候突然想到的...最近就有想写几篇关于继承虚函数的笔记,所以回家到之后就奋笔疾书的写出来发布了 应用sizeof函数求类巨细这个问题在很多面试,口试题中很轻易考,而涉及到类的时候 ...

  10. Js Pattern - Namespace Pattern

    bad code // BEFORE: 5 globals // Warning: antipattern // constructors function Parent() {} function ...