找零程序出错的原因在于,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类型表示,计算结果是...
Java编程语言中的“JAVA解惑”涉及到一些常见但容易引起混淆的概念,主要集中在整数的奇偶性判断和浮点数的精度问题上。 首先,我们来看“表达式谜题”。在Java中,判断一个整数是否为奇数通常会使用取余运算符 `%`...
### Java解惑知识点详解 #### 一、表达式谜题概览 本书《Java解惑》专注于探索Java编程语言及核心类库中的复杂细节。作者通过一系列精心设计的谜题来帮助读者深入理解Java中的一些棘手问题。本书共包含了95个谜题...
在“Java解惑.zip”这个压缩包中,我们有“Java解惑.pdf”这份文档,它可能包含了对Java编程中的一些常见疑惑和难题的解答。 首先,让我们探讨“谜题1——表达式谜题”。在Java中,表达式是用于计算值的语句,它们...
本篇将主要针对“Java解惑”这一主题,探讨其中的两个重要谜题:谜题1 - 奇数性与谜题2 - 找零时刻。这两个问题触及到Java语言的基础知识,包括逻辑运算、类型转换以及数学操作。 首先,我们来看谜题1 - 奇数性。在...
### Java解惑知识点详解 #### 一、表达式谜题 **谜题1:奇数性** - **描述**:程序看似应该返回一个布尔值,表明一个数字是否为奇数,但结果却出乎意料。 - **解惑**:在进行模运算时,需要注意负数的情况。当输入...
接下来是“找零时刻”的谜题。在计算找零时,使用`double`类型可能会导致精度问题。由于二进制浮点数无法精确表示某些十进制数,如0.1,所以在进行浮点数运算时,可能会得到预期之外的结果。在例子中,`2.00 - 1.10`...
2. **找零时刻**:此谜题可能涉及到浮点数的精度问题,由于浮点数在计算机中的存储方式,可能导致计算结果与预期有微小的误差。 3. **长整除**:长整数的除法运算可能会有不同于整数除法的规则,谜题3可能是讨论这...
#### 二、找零时刻:货币计算的陷阱 **谜题背景** 本谜题探讨了货币计算中的一个常见问题:如何准确地计算找零金额。这个问题涉及到Java中双精度浮点数(`double`类型)的表示和计算精度问题。 **谜题描述** 谜题...
【Java解惑很全的题目】是一份专为Java学习者设计的疑难解答文档,它包含了一系列关于Java编程语言的问题和谜题,旨在帮助读者深入理解Java的核心概念、语法特性和编程技巧。以下是对其中部分题目及其涉及知识点的...
**标题**: 找零时刻 **描述**: 本节探讨了在Java中进行浮点数运算时可能遇到的精度问题。 **详细解释**: 在实际应用中,比如财务计算场景,我们需要确保计算结果的准确性。然而,由于浮点数(如 `float` 和 `...
### JAVA解惑知识点详解 #### 一、表达式谜题:奇数判断 **知识点概述:** 本节探讨了一个常见的编程问题:如何准确地判断一个整数是否为奇数。虽然这个问题看似简单,但如果不小心处理Java中的取余运算符(`%`)...
#### 二、找零时刻:二进制浮点数的局限性 **谜题背景** 在实际应用中,经常需要处理货币相关的计算,例如找零。下面的例子展示了在使用Java的双精度浮点数(`double`)时可能会遇到的问题。 **问题描述** 假设有...
### Java解惑知识点详解 #### 一、表达式谜题:奇数性的判断 ##### 谜题背景 本节讨论了一个旨在判断整数是否为奇数的Java方法`isOdd`,并揭示了该方法在处理负数时存在的问题。 ##### 原始方法逻辑 ```java ...
谜题2:找零时刻 在这个问题中,Tom用一张2美元的钞票支付1.10美元的商品,我们期望程序能返回0.90美元的找零。然而,当使用`double`类型进行计算时,由于浮点数的二进制表示不精确,结果可能会出现意料之外的误差。...
#### 找零时刻谜题:浮点数运算的陷阱 **题目背景:** 本题旨在考察面试者对Java中浮点数运算的理解,特别是对于浮点数表示不精确性的认识。 **题目描述:** 题目给出了一段代码,用于模拟一个简单的找零场景。...