今天老师问了这么一个问题:
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工具设置输出精度的方法改正程序:
- System.out.pringln("%.2f%n"2.00-1.10");
这条语句打印的结果正确,但并不表示它就是对底层问题的通用解决方案:它使用的仍旧是二进制浮点数的double运算。浮点运算在一个范围很广的值域上提供了很好的近似,但是通常不能产生精确的结果。二进制浮点对于货币计算是非常不合适的,因为它不可能将0.1或者10的其他任何次幂,精确的表示为一个有限长度的二进制小数。
解决该问题的一种方式就是使用某种整数类型。例如int或者long,并且以分为单位来执行计算。如果采纳了此路线,请确保改整数类型大到足以表示程序中将要用到的所有值。对该谜题来说,int就足够了。下面使用int类型,以分为单位表示货币值后重写的println语句:
- System.out.println((200-190) + "cents");
解决改问题的另一个方式就是使用执行精确小数运算的BigDecimal。它还可以通过JDBC与SQLDECIMAL类型进行互操作。这里要注意一点:一定要用BigDecimal(String)构造器,而千万不要用BigDecimal(double)。后一个构造器将用他的参数的精确值来创建一个实例。例如new BigDecimal(.1),它将返回一个BigDecimal,也即0.100000000000000055511151231257827021181583404541015625.正确使用BigDecimal,程序就可以输出我们所需要的结果0.90:
- import java.math.BigDecimal;
- public class Change{
- public static void main(String[] args){
- System.out.println(new BigDecimal("2.00").subtract(new BigDecimal("1.10")));
- }
- }
在需要精确答案的地方,要避免使用float和double;对于货币运算,要使用int,long,BigDecimal。
分享到:
相关推荐
例如,在文档中提到的找零问题中,`System.out.println(2.00-1.10);`的结果可能不是我们期望的`0.90`,而是`0.***`。这是因为`1.1`无法被精确表示为`double`,而`2.00-1.10`计算后的结果也不是最接近`0.90`的`double...
**标题**: 找零时刻 **描述**: 本节探讨了在Java中进行浮点数运算时可能遇到的精度问题。 **详细解释**: 在实际应用中,比如财务计算场景,我们需要确保计算结果的准确性。然而,由于浮点数(如 `float` 和 `...
当尝试计算找零金额 `2.00 - 1.10` 时,由于 `1.1` 无法精确表示为二进制浮点数,它会被近似为一个略微小于 `1.1` 的值。因此,`2.00 - 1.10` 的结果不是预期的 `0.9`,而是接近 `0.9` 的一个不精确的浮点数表示。...
在上述示例中,尝试计算找零金额时,使用了`System.out.println(2.00 - 1.10);`。尽管期望输出是0.90,但实际上输出的是0.***。这是因为1.10不能被精确表示为二进制浮点数,所以在计算机中存储的是最接近的值。 ...
文档中提到的找零时刻问题便是因浮点数精度问题引发的典型案例。在使用`System.out.println(2.00-1.10);`时,期望输出的是0.90,但实际上输出的是0.***。这是因为1.1这个数值无法精确地以double类型表示,计算结果是...
#### 找零时刻谜题:浮点数运算的陷阱 **题目背景:** 本题旨在考察面试者对Java中浮点数运算的理解,特别是对于浮点数表示不精确性的认识。 **题目描述:** 题目给出了一段代码,用于模拟一个简单的找零场景。...
#### 二、找零时刻:货币计算中的精度问题 ##### 谜题背景 本节探讨了一段程序在处理货币找零时出现的精度问题。 ##### 代码示例 ```java public class Change { public static void main(String[] args) { ...
**实例描述**:计算找零问题,尝试从`2.00`中减去`1.10`并期望得到`0.90`作为结果。 **知识点详解**: 1. **浮点数的存储机制**:Java中`double`类型的数值采用IEEE 754标准存储,意味着某些十进制小数无法被精确...
#### 谜题2:找零问题 第二个谜题涉及到浮点数的运算和精度问题。具体问题描述如下: 假设Tom在一家汽车配件店买了一个价值1.10美元的火花塞,但他只有一张2美元的纸币。如果他用这张2美元的纸币付款,那么应找回...
#### 二、货币计算问题:精确找零的挑战 第二个谜题涉及到货币计算中的常见陷阱。问题描述如下:Tom 在一家汽车配件店买了一个价值 $1.10 的火花塞,他用一张两美元的钞票支付。程序尝试计算应找回的零钱金额,但...
接下来是“找零时刻”的谜题。在计算找零时,使用`double`类型可能会导致精度问题。由于二进制浮点数无法精确表示某些十进制数,如0.1,所以在进行浮点数运算时,可能会得到预期之外的结果。在例子中,`2.00 - 1.10`...
- **问题描述**:假设 Tom 在一家汽车配件店购买了一个价值 $1.10 的火花塞,他使用了一张 $2 的钞票进行支付。代码尝试计算应找回的零钱数额。 **问题分析** - 在Java中,`double` 类型用于表示双精度浮点数,但...
在找零的场景中,如果直接用`2.00 - 1.10`计算,可能会得到不准确的结果,例如`0.8999999999999999`,这是因为`1.1`不能精确表示为二进制浮点数,计算过程中引入了误差。为了解决这个问题,避免使用浮点数进行货币...
在给定的示例中,`2.00 - 1.10`实际计算的结果不是0.9,而是接近但不等于0.9的一个值。为了得到预期的输出,我们通常会使用`printf`函数来控制输出的小数位数,但这并不能改变计算过程中的精度问题。对于涉及货币...