Java Double 类
最后修改时间:2025 年 4 月 13 日
java.lang.Double 类是原始 double 类型的包装类,提供用于处理双精度浮点数的实用方法。 它允许在原始 double 值和 Double 对象之间进行转换,从而使它们可以在集合、泛型和面向对象的编程环境中使用。
除了转换函数之外,Double 类还为数值运算提供有用的常量和方法。 它包括用于解析、比较和检查特殊浮点值(例如 NaN (非数字) 和无穷大)的功能。 这些功能有助于确保处理浮点算术时的精度和正确性。
Double 类方法
Double 类提供了多个用于处理 double 值的静态和实例方法。 一些关键方法包括
parseDouble(String s)- 将字符串转换为原始double类型,对无效输入抛出NumberFormatException。valueOf(double d)- 返回一个Double对象,表示指定的原始double值。doubleValue()- 从Double对象中提取原始double值。compare(Double d1, Double d2)- 比较两个Double对象,根据它们的相对值返回负数、零或正数。isNaN(double d)- 确定给定的double值是否为NaN,它发生在未定义的数学运算中。
通过利用这些方法,Double 类促进了 Java 中无缝转换、比较和数值运算,从而确保了处理浮点数据时的可靠性。
创建 Double 对象
Double 类提供了多种方法来创建表示双精度浮点数的实例。 可以使用 valueOf 方法实例化对象,由于它具有缓存常用值的潜力,因此是首选方法。 此外,Java 的自动装箱机制在必要时自动将原始 double 值转换为 Double 对象。
package com.zetcode;
public class Main {
public static void main(String[] args) {
Double d1 = Double.valueOf(3.14159);
Double d2 = Double.valueOf("3.14159");
// Using autoboxing
Double d3 = 3.14159;
System.out.println("d1: " + d1);
System.out.println("d2: " + d2);
System.out.println("d3: " + d3);
// Converting back to primitive
double primitive = d1;
System.out.println("Primitive value: " + primitive);
}
}
此示例演示了创建 Double 对象的不同方法。 valueOf 方法通常是首选方法,因为它可能会重用现有实例而不是创建新实例。 自动装箱简化了转换,在需要时自动将原始 double 值包装到 Double 对象中,从而减少了手动对象创建。
解析 Double 值
parseDouble 方法将字符串转换为原始 double 类型。 valueOf 方法将字符串转换为 Double 对象。 两者都会对无效输入抛出 NumberFormatException。
package com.zetcode;
public class Main {
public static void main(String[] args) {
String numStr1 = "3.14159";
String numStr2 = "-123.456";
String invalidStr = "3.14.159";
// Parsing to primitive double
double d1 = Double.parseDouble(numStr1);
double d2 = Double.parseDouble(numStr2);
// Parsing to Double object
Double dObj1 = Double.valueOf(numStr1);
Double dObj2 = Double.valueOf(numStr2);
System.out.println("d1: " + d1);
System.out.println("d2: " + d2);
System.out.println("dObj1: " + dObj1);
System.out.println("dObj2: " + dObj2);
try {
double invalid = Double.parseDouble(invalidStr);
} catch (NumberFormatException e) {
System.out.println("Invalid number format: " + invalidStr);
}
}
}
此示例显示了如何将字符串解析为 double 值。 parseDouble 返回一个原始类型,而 valueOf 返回一个 Double 对象。 两种方法都会对格式错误的输入抛出异常。
特殊的 Double 值
特殊的浮点值是由某些数学运算产生的
- NaN (非数字): 表示未定义的结果,例如
0/0或Infinity - Infinity。 NaN 值会在计算中传播。 - 正无穷大: 当一个值超过最大的 double 值时发生,例如
1.0 / 0.0。 - 负无穷大: 表示一个无限小的值,例如
-1.0 / 0.0。
这些值遵循浮点算术中的特定规则。 涉及 NaN 的运算几乎总是导致 NaN。 无穷大值在乘法或加法中表现如预期,但在除以另一个无穷大时可能会变为 NaN。
通过利用特殊值及其相应的验证方法,开发人员可以有效地处理浮点计算中的边缘情况,并防止意外的数值错误。
package com.zetcode;
public class Main {
public static void main(String[] args) {
double nanValue = Double.NaN;
double posInf = Double.POSITIVE_INFINITY;
double negInf = Double.NEGATIVE_INFINITY;
System.out.println("NaN: " + nanValue);
System.out.println("Positive Infinity: " + posInf);
System.out.println("Negative Infinity: " + negInf);
System.out.println("Is NaN? " + Double.isNaN(nanValue));
System.out.println("Is Infinity? " + Double.isInfinite(posInf));
// Operations with special values
System.out.println("NaN + 1: " + (nanValue + 1)); // NaN propagates
System.out.println("Infinity * 2: " + (posInf * 2)); // Still infinity
System.out.println("Infinity / Infinity: " + (posInf / posInf)); // Results in NaN
}
}
此示例演示了特殊的浮点值——NaN、POSITIVE_INFINITY 和 NEGATIVE_INFINITY——在 Java 中的行为。 它展示了如何使用 isNaN 和 isInfinite 检查这些值,并说明了它们如何在算术运算中传播,从而帮助开发人员有效地处理数值计算中的边缘情况。
比较 Double 值
由于浮点精度误差,比较 double 值需要特别小心。 使用 == 的直接相等性检查在处理小数值时可能会产生意外的结果。 compare 和 compareTo 方法提供了可靠的比较机制,可以正确处理 NaN 和无穷大等特殊值。
浮点精度限制可能导致不准确的相等性检查。 为了确保正确的比较,请遵循以下最佳实践
- 使用
Double.compare(d1, d2): 此方法正确处理特殊值,例如NaN和无穷大。 - 避免直接相等性检查 (
d1 == d2): 微小的精度差异可能会导致不准确的结果。 - 使用容差进行近似相等性检查:
Math.abs(d1 - d2) < tolerance考虑了小的浮点误差。 - 小心使用
NaN: 任何涉及NaN的比较都会返回意外的结果,因为NaN是无序的。 - 使用
BigDecimal进行精确的十进制比较: 与double不同,BigDecimal提供了精确的十进制算术,从而防止了舍入误差。 使用BigDecimal.compareTo进行可靠的相等性检查。
对于需要精确十进制值的场景,例如财务计算,BigDecimal 是首选。 它避免了浮点不准确性,并允许控制比例和舍入行为,从而确保数值计算的正确性。
package com.zetcode;
public class Main {
public static void main(String[] args) {
Double d1 = 1.23456;
Double d2 = 1.23457;
Double d3 = Double.NaN;
Double d4 = Double.POSITIVE_INFINITY;
// Using compareTo method (instance method)
System.out.println("d1 compareTo d2: " + d1.compareTo(d2));
System.out.println("d3 compareTo d1: " + d3.compareTo(d1));
System.out.println("d4 compareTo d1: " + d4.compareTo(d1));
// Using static compare method
System.out.println("Compare d1 and d2: " + Double.compare(d1, d2));
// Equality comparison with tolerance
double tolerance = 0.0001;
boolean nearlyEqual = Math.abs(d1 - d2) < tolerance;
System.out.println("d1 nearly equals d2: " + nearlyEqual);
}
}
此示例演示了在 Java 中比较浮点值的不同方法。 它展示了 compareTo 方法如何正确处理排序,即使使用 NaN 和无穷大等特殊值也是如此。 静态 Double.compare 方法提供了另一种比较 Double 实例的方法。 此外,该示例强调了在使用容差值检查近似相等性时,确保可靠比较的重要性,即使存在微小的浮点精度误差也是如此。
转换 Double 值
Double 类提供了多种方法来在 double 值和其他原始类型之间进行转换。 这些方法允许无缝的数据转换,但在将浮点数转换为整数类型时,重要的是要考虑潜在的精度损失。
常见的转换方法包括 intValue、longValue 和 floatValue。 转换为整数类型时,小数部分会被截断而不是舍入,这可能会导致预期值的差异。
转换 Double 值时,请考虑以下几点
- 截断与舍入: 将
double转换为整数类型会删除小数部分,而不是舍入。 - 精度损失: 由于存储格式的差异,转换为
float可能会引入轻微的精度误差。 - 溢出风险: 将大的
double值转换为byte或short可能会导致意外的溢出行为。 - 十六进制表示:
toHexString()方法提供了一种基于 16 的浮点格式,可用于调试或存储。
package com.zetcode;
public class Main {
public static void main(String[] args) {
Double d = 123.456789;
// Converting to other primitive types
int intVal = d.intValue(); // Truncates decimal part
long longVal = d.longValue();
float floatVal = d.floatValue(); // Potential precision loss
byte byteVal = d.byteValue(); // Risk of overflow for large values
short shortVal = d.shortValue();
System.out.println("Original double: " + d);
System.out.println("intValue: " + intVal);
System.out.println("longValue: " + longVal);
System.out.println("floatValue: " + floatVal);
System.out.println("byteValue: " + byteVal);
System.out.println("shortValue: " + shortVal);
// Converting to String
String strVal = d.toString();
String hexStr = Double.toHexString(d);
System.out.println("toString: " + strVal);
System.out.println("toHexString: " + hexStr);
}
}
此示例演示了安全高效的转换方法,重点介绍了开发人员在使用浮点数据时应考虑的潜在陷阱。
Double 常量和限制
Double 类提供了有用的常量,这些常量表示双精度浮点数的限制。 这些包括 MAX_VALUE、MIN_VALUE 和 MAX_EXPONENT。
package com.zetcode;
public class Main {
public static void main(String[] args) {
System.out.println("MAX_VALUE: " + Double.MAX_VALUE);
System.out.println("MIN_VALUE: " + Double.MIN_VALUE);
System.out.println("MIN_NORMAL: " + Double.MIN_NORMAL);
System.out.println("MAX_EXPONENT: " + Double.MAX_EXPONENT);
System.out.println("MIN_EXPONENT: " + Double.MIN_EXPONENT);
System.out.println("SIZE: " + Double.SIZE + " bits");
System.out.println("BYTES: " + Double.BYTES + " bytes");
// Demonstrating overflow
double max = Double.MAX_VALUE;
System.out.println("MAX_VALUE * 2: " + (max * 2));
// Demonstrating underflow
double min = Double.MIN_VALUE;
System.out.println("MIN_VALUE / 2: " + (min / 2));
}
}
此示例显示了双精度浮点数的限制。 MAX_VALUE 是最大的有限正值,而 MIN_VALUE 是最小的正非零值。 溢出会导致无穷大,而下溢会导致零。
来源
在本文中,我们介绍了 Java Double 类的基本方法和特性。 了解这些概念对于在 Java 应用程序中使用浮点数至关重要。
作者
列出所有Java教程。