java开发150个建议(16)


// 模拟取余计算,dividend被除数,divisor除数public static int remainder(int dividend, int divisor) {return dividend - dividend / divisor * divisor;}
看到这段程序,大家都会心的笑了,原来Java这么处理取余计算的呀,根据上面的模拟取余可知,当输入-1的时候,运算结果为-1,当然不等于1了,所以它就被判定为偶数了,也就是我们的判断失误了 。问题明白了,修正也很简单,改为判断是否是偶数即可 。代码如下: i % 2 == 0 ? "偶数" : "奇数";
注意:对于基础知识,我们应该"知其然,并知其所以然" 。
回到顶部
建议22:用整数类型处理货币
在日常生活中,最容易接触到的小数就是货币,比如,你付给售货员10元钱购买一个9.6元的零食,售货员应该找你0.4元,也就是4毛钱才对,我们来看下面的程序:
public class Client22 {public static void main(String[] args) {System.out.println(10.00-9.60);}}
我们的期望结果是0.4,也应该是这个数字,但是打印出来的却是:0.00036,这是为什么呢?
这是因为在计算机中浮点数有可能(注意是有可能)是不准确的,它只能无限接近准确值,而不能完全精确 。为什么会如此呢?这是由浮点数的存储规则所决定的,我们先来看看0.4这个十进制小数如何转换成二进制小数,使用"乘2取整,顺序排列"法(不懂,这就没招了,这太基础了),我们发现0.4不能使用二进制准确的表示,在二进制数世界里它是一个无限循环的小数,也就是说,"展示" 都不能 "展示",更别说在内存中存储了(浮点数的存储包括三部分:符号位、指数位、尾数,具体不再介绍),可以这样理解,在十进制的世界里没有办法唯一准确表示1/3,那么在二进制的世界里当然也无法准确表示1/5(如果二进制也有分数的话倒是可以表示),在二进制的世界里1/5是一个无限循环的小数 。
大家可能要说了,那我对结果取整不就对了吗?代码如下
public class Client22 {public static void main(String[] args) {NumberFormat f = new DecimalFormat("#.##");System.out.println(f.format(10.00-9.60));}}
打印出的结果是0.4,看似解决了 。但是隐藏了一个很深的问题 。我们来思考一下金融行业的计算方法,会计系统一般记录小数点后的4为小数,但是在汇总、展现、报表中、则只记录小数点后的2位小数,如果使用浮点数来计算货币,想想看,在大批量加减乘除后结果会有很大的差距(其中还涉及到四舍五入的问题)!会计系统要求的就是准确,但是因为计算机的缘故不准确了,那真是罪过,要解决此问题有两种方法:
(1)、使用
是专门为弥补浮点数无法精确计算的缺憾而设计的类,并且它本身也提供了加减乘除的常用数学算法 。特别是与数据库类型的字段映射时,是最优的解决方案 。
(2)、使用整型
把参与运算的值扩大100倍,并转为整型,然后在展现时再缩小100倍,这样处理的好处是计算简单,准确,一般在非金融行业(如零售行业)应用较多 。此方法还会用于某些零售POS机,他们输入和输出的全部是整数,那运算就更简单了.
回到顶部
建议23:不要让类型默默转换
我们做一个小学生的题目,光速每秒30万公里,根据光线的旅行时间,计算月球和地球,太阳和地球之间的距离 。代码如下:
1 public class Client23 {2// 光速是30万公里/秒,常量3public static final int LIGHT_SPEED = 30 * 10000 * 1000;4 5public static void main(String[] args) {6System.out.println("题目1:月球照射到地球需要一秒,计算月亮和地球的距离 。");7long dis1 = LIGHT_SPEED * 1;8System.out.println("月球与地球的距离是:" + dis1 + " 米 ");9System.out.println("-------------------------------");10System.out.println("题目2:太阳光照射到地球需要8分钟,计算太阳到地球的距离.");11// 可能要超出整数范围,使用long型12long dis2 = LIGHT_SPEED * 60 * 8;13System.out.println("太阳与地球之间的距离是:" + dis2 + " 米");14}15 }