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