2.00-1.10(找零时刻分析)问题分析

今天老师问了这么一个问题:

public class program {

      

   //判断是否为奇数,是就返回true   

public static boolean isOdd(int i){

       return i % 2==1;       

   }   

public static void main(String[] args){

       for(int i=-2;i<=2;i++){   

       System.out.println(isOdd(i));   

       }   

       System.out.println("ssss"+(2-1.1));   

        }

}

//请问,这段程序将会输出什么?   

//请解释并优化该代码

 

开始以为也没什么,但结果还是不容你想到的。

结果是:false false true false 0.8999999999999999

为什么是这样的呢?

其实是double的精度问题。0.1,无法用二进制精确表示,如果N是负数,10的N次幂无法用二进制精确表示。

既然不精确 如:(System.out.println(3-2.99); 输出:0.009999999999999787),总之差一点点,可以理解。在JAVA中要取得精确的带小数的值,用BigDecimal  即:System.out.println("优化后代码:"+new BigDecimal("2.00").subtract(new BigDecimal("1.10")));

 

==============================================================完美分界线

 

 

如下是转载 http://liuwei1981.iteye.com/blog/162891 的具体分析:

1.1这个数字不能被精确的表示为一个double,因此被表示为最接近它的double值。改程序从2中减去的就是这个值。遗憾的是,这个计算的结果并不是最接近0.9的double值。作为结果的double值的最短表示就是你看到的那个程序输出的可恶的数字。

并不是所有的小数都可以用二进制浮点数精确表示。如果使用的是JDK5或者更新的版本,那么您可能会受其诱惑,通过使用printf工具设置输出精度的方法改正程序:

Java代码 
  1. System.out.pringln("%.2f%n"2.00-1.10");  

这条语句打印的结果正确,但并不表示它就是对底层问题的通用解决方案:它使用的仍旧是二进制浮点数的double运算。浮点运算在一个范围很广的值域上提供了很好的近似,但是通常不能产生精确的结果。二进制浮点对于货币计算是非常不合适的,因为它不可能将0.1或者10的其他任何次幂,精确的表示为一个有限长度的二进制小数

 

解决该问题的一种方式就是使用某种整数类型。例如int或者long,并且以分为单位来执行计算。如果采纳了此路线,请确保改整数类型大到足以表示程序中将要用到的所有值。对该谜题来说,int就足够了。下面使用int类型,以分为单位表示货币值后重写的println语句:

 

Java代码 
  1. System.out.println((200-190) + "cents");  

 

 解决改问题的另一个方式就是使用执行精确小数运算的BigDecimal。它还可以通过JDBC与SQLDECIMAL类型进行互操作。这里要注意一点:一定要用BigDecimal(String)构造器,而千万不要用BigDecimal(double)。后一个构造器将用他的参数的精确值来创建一个实例。例如new BigDecimal(.1),它将返回一个BigDecimal,也即0.100000000000000055511151231257827021181583404541015625.正确使用BigDecimal,程序就可以输出我们所需要的结果0.90:

 

Java代码 
  1. import java.math.BigDecimal;  
  2. public class Change{  
  3.   public static void main(String[] args){  
  4.         System.out.println(new BigDecimal("2.00").subtract(new BigDecimal("1.10")));  
  5.     }  
  6. }  

在需要精确答案的地方,要避免使用float和double;对于货币运算,要使用int,long,BigDecimal。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值