用整数类型处理货币

简介:
复制代码
1 public class Client {
2     public static void main(String[] args) {
3         System.out.println("10-9.5 = " + (10 - 9.5));
4         System.out.println("10-9.6 = " + (10 - 9.6));
5     }
6 }
复制代码

运行结果:

1 10-9.5 = 0.5
2 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在转换时就失真了, 可想而知,输出结果多了一段小尾巴也不足为奇了,它只是为了达到无限接近准确值这个原则而已。

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

对结果取整不就对了吗?

复制代码
1 public class Client {
2     public static void main(String[] args) {
3         NumberFormat f = new DecimalFormat("#.##");
4         System.out.println(f.format(10.00-9.60));
5     }
6 }
复制代码

 

运行结果:打印出0.4

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

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

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

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


本文转自SummerChill博客园博客,原文链接:http://www.cnblogs.com/DreamDrive/p/5424825.html,如需转载请自行联系原作者

相关文章
|
2月前
取一个整数a从右端开始的 4~7 位
取一个整数a从右端开始的 4~7 位。
23 7
|
3月前
比较三个整数大小
比较三个整数大小
58 13
|
3月前
|
存储 编译器 C语言
取一个整数a从右端开始的4~7位。
取一个整数a从右端开始的4~7位。
32 1
|
7月前
63.取一个整数a从右端开始的4~7位。
63.取一个整数a从右端开始的4~7位。
36 0
|
6月前
取一个整数 a 从右端开始的 4~7 位
【6月更文挑战第23天】取一个整数 a 从右端开始的 4~7 位。
46 9
|
7月前
求两个整数之和
两幅图片展示,无文字描述。第一张图片链接:`https://ucc.alicdn.com/pic/developer-ecology/jsj5v54nhc5lk_9a19903e665642b388dedfa69ba6dd98.jpg`,第二张图片链接:`https://ucc.alicdn.com/pic/developer-ecology/jsj5v54nhc5lk_9698cabf5d2f4ce38f6ea21a4ee8430e.jpg`。
37 0
|
7月前
将整数转换为枚举
将整数转换为枚举。
41 2
|
7月前
|
存储
整数类型
整数类型。
71 0
数字 金额 相关 转换
数字 金额 相关 转换
69 0
wustojc1006求2个整数的和
wustojc1006求2个整数的和
46 0