`
linvar
  • 浏览: 258879 次
  • 性别: Icon_minigender_1
  • 来自: 未定
社区版块
存档分类
最新评论

Java 程序中使用浮点数和小数

    博客分类:
  • java
阅读更多
在 Java 程序中使用浮点数和小数充满着陷阱。浮点数和小数不象整数一样“循规蹈矩”,不能假定浮点计算一定产生整型或精确的结果,虽然它们的确“应该”那样做。最好将浮点运算保留用作计算本来就不精确的数值,譬如测量。如果需要表示定点数(譬如,几美元和几美分),则使用 BigDecimal。


不要用浮点值表示精确值
一些非整数值(如几美元和几美分这样的小数)需要很精确。浮点数不是精确值,所以使用它们会导致舍入误差。因此,使用浮点数来试图表示象货币量这样的精确数量不是一个好的想法。使用浮点数来进行美元和美分计算会得到灾难性的后果。浮点数最好用来表示象测量值这类数值,这类值从一开始就不怎么精确。

用于较小数的 BigDecimal
从 JDK 1.3 起,Java 开发人员就有了另一种数值表示法来表示非整数:BigDecimal。BigDecimal 是标准的类,在编译器中不需要特殊支持,它可以表示任意精度的小数,并对它们进行计算。在内部,可以用任意精度任何范围的值和一个换算因子来表示 BigDecimal,换算因子表示左移小数点多少位,从而得到所期望范围内的值。因此,用 BigDecimal 表示的数的形式为 unscaledValue*10-scale。

用于加、减、乘和除的方法给 BigDecimal 值提供了算术运算。由于 BigDecimal 对象是不可变的,这些方法中的每一个都会产生新的 BigDecimal 对象。因此,因为创建对象的开销,BigDecimal 不适合于大量的数学计算,但设计它的目的是用来精确地表示小数。如果您正在寻找一种能精确表示如货币量这样的数值,则 BigDecimal 可以很好地胜任该任务。

所有的 equals 方法都不能真正测试相等
如浮点类型一样,BigDecimal 也有一些令人奇怪的行为。尤其在使用 equals() 方法来检测数值之间是否相等时要小心。equals() 方法认为,两个表示同一个数但换算值不同(例如,100.00 和 100.000)的 BigDecimal 值是不相等的。然而,compareTo() 方法会认为这两个数是相等的,所以在从数值上比较两个 BigDecimal 值时,应该使用 compareTo() 而不是 equals()。

另外还有一些情形,任意精度的小数运算仍不能表示精确结果。例如,1 除以 9 会产生无限循环的小数 .111111...。出于这个原因,在进行除法运算时,BigDecimal 可以让您显式地控制舍入。movePointLeft() 方法支持 10 的幂次方的精确除法。

使用 BigDecimal 作为互换类型
SQL-92 包括 DECIMAL 数据类型,它是用于表示定点小数的精确数字类型,它可以对小数进行基本的算术运算。一些 SQL 语言喜欢称此类型为 NUMERIC 类型,其它一些 SQL 语言则引入了 MONEY 数据类型,MONEY 数据类型被定义为小数点右侧带有两位的小数。

如果希望将数字存储到数据库中的 DECIMAL 字段,或从 DECIMAL 字段检索值,则如何确保精确地转换该数字?您可能不希望使用由 JDBC PreparedStatement 和 ResultSet 类所提供的 setFloat() 和 getFloat() 方法,因为浮点数与小数之间的转换可能会丧失精确性。相反,请使用 PreparedStatement 和 ResultSet 的 setBigDecimal() 及 getBigDecimal() 方法。

类似的,象 Castor 这样的 XML 数据绑定工具使用 BigDecimal 会生成小数值属性和元素(在 XSD 模式中支持这种基本数据类型)的 getter 和 setter。

构造 BigDecimal 数
对于 BigDecimal,有几个可用的构造函数。其中一个构造函数以双精度浮点数作为输入,另一个以整数和换算因子作为输入,还有一个以小数的 String 表示作为输入。要小心使用 BigDecimal(double) 构造函数,因为如果不了解它,会在计算过程中产生舍入误差。请使用基于整数或 String 的构造函数。

如果使用 BigDecimal(double) 构造函数不恰当,在传递给 JDBC setBigDecimal() 方法时,会造成似乎很奇怪的 JDBC 驱动程序中的异常。例如,考虑以下 JDBC 代码,该代码希望将数字 0.01 存储到小数字段:

PreparedStatement ps =
    connection.prepareStatement("INSERT INTO Foo SET name=?, value=?");
  ps.setString(1, "penny");
  ps.setBigDecimal(2, new BigDecimal(0.01));
  ps.executeUpdate();

在执行这段似乎无害的代码时会抛出一些令人迷惑不解的异常(这取决于具体的 JDBC 驱动程序),因为 0.01 的双精度近似值会导致大的换算值,这可能会使 JDBC 驱动程序或数据库感到迷惑。JDBC 驱动程序会产生异常,但可能不会说明代码实际上错在哪里,除非意识到二进制浮点数的局限性。相反,使用 BigDecimal("0.01") 或 BigDecimal(1, 2) 构造 BigDecimal 来避免这类问题,因为这两种方法都可以精确地表示小数。
分享到:
评论

相关推荐

    Java输入浮点数分别输出整数部分和小数部分

    Java输入浮点数分别输出整数部分和小数部分

    JAVA中浮点数的运算

    在Java编程语言中,浮点数的运算涉及到的是数值计算,特别是小数部分的处理。浮点数在计算机内部是以二进制表示的,这与我们通常使用的十进制系统不同,因此在进行浮点数运算时可能会出现精度丢失的问题。这篇博客...

    Java 程序将两个浮点数相乘.docx

    在 Java 编程语言中,处理浮点数的运算与整数运算略有不同,因为浮点数涉及到小数部分的计算。本程序演示了如何在 Java 中将两个浮点数相乘并显示结果。首先,我们需要了解浮点类型的基础知识。 在 Java 中,有两种...

    用java从文件中读取浮点数

    在Java中,主要使用两种浮点数类型:`float`(单精度)和`double`(双精度)。`double`类型的精度更高,通常用于需要高精度计算的场景。 #### 1.2 文件读取机制 在Java中,文件读取通常涉及到输入流(`InputStream`...

    疯狂Java讲义 浮点数转换成人民币读法

    在实际编程中,我们还可以考虑使用Java的NumberFormat和DecimalFormat类进行更复杂的格式化操作,包括货币格式。这些类提供了丰富的功能,如指定小数位数、千位分隔符、货币符号等,可以满足更复杂的格式化需求。 ...

    输入一个浮点数,输出此数的整数部分和小数部分

    适用于java的小练习.希望对大家有帮助.

    Java与MySQL中小数保存问题解析.pptx.pptx

    当处理小数时,确保在SQL语句中使用正确的数据类型,并且在Java代码中正确地转换和处理结果。 常见问题还包括在进行浮点数运算时可能出现的精度丢失,以及在设计数据库表结构时选择合适的数据类型。例如,如果业务...

    java实现小数、百分数值处理组件

    在Java编程中,处理小数和百分数是常见的任务,特别是在财务、统计或者科学计算等领域。这个名为"java实现小数、百分数值处理组件"的工具包,显然是为了解决这些问题而设计的。下面我们将详细探讨相关的知识点。 ...

    HEX与浮点数相互转换

    HEX(十六进制)是计算机中广泛使用的数字表示方式,尤其在内存和CPU指令中,而浮点数则用于表示带有小数部分的数值,常用于科学计算和精确度要求较高的场景。转换这两者之间的形式对于理解和调试程序、存储数据以及...

    国开电大 Java语言程序设计 形考任务1-2答案.pdf

    7. **浮点类型限制**:Java中的浮点类型包括`float`和`double`,声明`float f=5.2`是错误的,因为5.2是一个双精度浮点数,需要强制类型转换才能赋值给`float`。 8. **变量交换**:在Java中,交换两个变量的值通常...

    Java中浮点数精度问题的解决方法

    总的来说,Java中解决浮点数精度问题的关键是使用BigDecimal类,并且要注意构造方法的选择,避免在转换过程中引入额外的精度损失。在编写涉及金融计算或需要高度精确性的程序时,使用BigDecimal是最佳实践。同时,...

    Java关键字大全 Java关键字大全

    Java编程语言中的关键字是语言语法的核心组成部分,它们具有特殊的含义并用于特定的编程目的。以下是一些Java关键字的详细说明: 1. `abstract`:`abstract`关键字用于声明抽象类和抽象方法。抽象类不能被实例化,...

    算法-计算浮点数相除的余(信息学奥赛一本通-T1029)(包含源程序).rar

    在信息学奥赛中,计算浮点数相除的余数是一个常见的问题,这涉及到数值计算、浮点数处理和编程技巧。浮点数运算在计算机科学中扮演着至关重要的角色,尤其是在解决数学和工程问题时。这个题目可能是为了帮助参赛者...

    4字节浮点数内码转换

    4字节浮点数,也称为单精度浮点数,遵循国际标准IEEE 754,这种格式在大多数现代计算机系统中广泛使用。4字节浮点数能够表示大约6到9个有效数字,并且具有一定的精度和范围。 首先,让我们了解浮点数的基本结构。...

    浮点数开方.rar

    浮点数开方是计算机科学中的一个重要概念,特别是在数值计算和数学运算中。浮点数是一种表示实数的方式,它允许我们处理不精确的数值,比如带有小数的数字。在计算机内部,浮点数通常按照IEEE 754标准进行存储和操作...

    单精度&双精度浮点数与十六进制数相互转换

    在实际编程中,大多数编程语言如C++、Java、Python等都提供了内置函数来进行浮点数和十六进制之间的转换。例如,在Python中,可以使用`float.hex()`和`float.fromhex()`方法实现这一过程。 理解这些转换机制对编程...

    浮点数转换工具.7z

    5. **编程语言中的浮点数操作**: 不同的编程语言对浮点数处理有不同的内置函数和库,转换工具可能提供了这些语言间数据类型的转换,比如C++的`double`到Java的`double`。 6. **应用场景**: 这样的工具对于程序员...

    西门子 S7-200 PLC上位机通信 浮点数

    对于标签中的"C++"、"vb"、"delphi"、"vc++"和"C++builder",这些都是编程语言或开发环境,它们都可以用来编写上位机程序,与S7-200 PLC进行交互。例如,使用C++时,可以利用第三方库(如libnodave或cpps7)来实现与...

    浮点数与十六进制转换.rar

    浮点数和十六进制转换是计算机科学中的基础概念,特别是在数据存储、计算以及网络通信等领域有着广泛应用。本文将深入探讨浮点数的表示方法、十六进制的基础知识,以及如何进行浮点数到十六进制的转换。 首先,我们...

Global site tag (gtag.js) - Google Analytics