如果我不对 double 进行任何操作,我可以在 Java 中保持精度吗?
Can I retain precision in Java if I make no operations to a double?
我想以双精度存储从 0.00 到 10.00 的值。我只需要 2 位数的精度。
如果我不对双打进行任何操作,我能保证我总是得到我存储在变量中的内容吗?
我正在查看 this answer,并测试了这段代码:
double a = 1.2;
double b = 1.1;
System.out.println(a - b);
System.out.println(a);
System.out.println(b);
第一个打印输出一个不精确的值,据我理解,解释是机器必须多么不精确地表示数字。但是,为什么其他两个打印输出精确值?就因为我没做手术?我可以假设它永远是真的吗?
不精确来自于将数字表示为 double
(floating point number)。
虽然它确实在浮点值上使用算术,正如我上面所说的,但问题在于值的存储,尽管打印方法经常试图向我们隐藏它。这个答案应该包含足够的细节:
如果你想存储(和操作)十进制数到小数点后两位的精度,而不是更多,那么你不应该使用 double
s(或 float
s) .您应该改用精确数字(例如 int
s 或 long
s)。对于两位小数,您可以只使用 100 == 1.0
,或使用 BigDecimal
class.
以下是打印双精度值内容的一些不同尝试:
import java.math.*;
public class FloatShow {
public static void main(String ... args) {
System.out.println(1.2);
System.out.println(new Double(1.2).toString());
System.out.println(new BigDecimal(1.2).toString());
}
}
这会打印出
1.2
1.2
1.1999999999999999555910790149937383830547332763671875
println 方法给出了一个 double 框并调用 toString,类似地,Double 使用 toString,它正在为您做一些舍入。 BigDecimal 使用原始值构造一个实例,并在不进行清理的情况下呈现它。所以你关于精度的假设是无效的。
浮点数和固定小数是两个不同的概念。 Here is the definition of floating point arithmetic in wikipedia:
In computing, floating-point arithmetic (FP) is arithmetic using formulaic representation of real numbers as an approximation to support a trade-off between range and precision. For this reason, floating-point computation is often found in systems which include very small and very large real numbers, which require fast processing times.
但固定小数(如BigDecimal)不同,它存储的是单个数字。 BigDecimal 使用起来较慢,但它不会像浮点数那样进行范围-精度权衡。
浮点数适用于计算瓶颈的图形和工程应用,输入不完全精确(但在已知误差范围内精确)并且可以计算出速度值得权衡.对于许多业务应用程序来说,性能差异不是问题,因为其他因素始终是瓶颈,值是确切已知的,并且准确性是不可协商的。
Java 对其 double
类型使用 IEEE-754 binary32 格式。此类型具有 属性,对于其指数范围内的数字,如果任何 15 位或更少有效数字的十进制数字转换为 double
(使用舍入到最接近的数,并列到偶数) , 并将结果 double
转换回 15 位十进制数字,结果等于原始数字。
对于浮点数的默认格式,Java 生成的数字刚好足以 uniquely distinguish 浮点格式中的数字。
这两个属性的结果是,将具有 15 个或更少有效数字的十进制数字转换为 double
,然后使用默认格式将其转换回十进制将产生与原始数字相同的结果。它可能在某些方面有所不同。例如,原始数字可能有生成的数字没有的尾随零,例如“3.00”到“3”或“123.4500”到“123.45”。
我想以双精度存储从 0.00 到 10.00 的值。我只需要 2 位数的精度。 如果我不对双打进行任何操作,我能保证我总是得到我存储在变量中的内容吗?
我正在查看 this answer,并测试了这段代码:
double a = 1.2;
double b = 1.1;
System.out.println(a - b);
System.out.println(a);
System.out.println(b);
第一个打印输出一个不精确的值,据我理解,解释是机器必须多么不精确地表示数字。但是,为什么其他两个打印输出精确值?就因为我没做手术?我可以假设它永远是真的吗?
不精确来自于将数字表示为 double
(floating point number)。
虽然它确实在浮点值上使用算术,正如我上面所说的,但问题在于值的存储,尽管打印方法经常试图向我们隐藏它。这个答案应该包含足够的细节:
如果你想存储(和操作)十进制数到小数点后两位的精度,而不是更多,那么你不应该使用 double
s(或 float
s) .您应该改用精确数字(例如 int
s 或 long
s)。对于两位小数,您可以只使用 100 == 1.0
,或使用 BigDecimal
class.
以下是打印双精度值内容的一些不同尝试:
import java.math.*;
public class FloatShow {
public static void main(String ... args) {
System.out.println(1.2);
System.out.println(new Double(1.2).toString());
System.out.println(new BigDecimal(1.2).toString());
}
}
这会打印出
1.2
1.2
1.1999999999999999555910790149937383830547332763671875
println 方法给出了一个 double 框并调用 toString,类似地,Double 使用 toString,它正在为您做一些舍入。 BigDecimal 使用原始值构造一个实例,并在不进行清理的情况下呈现它。所以你关于精度的假设是无效的。
浮点数和固定小数是两个不同的概念。 Here is the definition of floating point arithmetic in wikipedia:
In computing, floating-point arithmetic (FP) is arithmetic using formulaic representation of real numbers as an approximation to support a trade-off between range and precision. For this reason, floating-point computation is often found in systems which include very small and very large real numbers, which require fast processing times.
但固定小数(如BigDecimal)不同,它存储的是单个数字。 BigDecimal 使用起来较慢,但它不会像浮点数那样进行范围-精度权衡。
浮点数适用于计算瓶颈的图形和工程应用,输入不完全精确(但在已知误差范围内精确)并且可以计算出速度值得权衡.对于许多业务应用程序来说,性能差异不是问题,因为其他因素始终是瓶颈,值是确切已知的,并且准确性是不可协商的。
Java 对其 double
类型使用 IEEE-754 binary32 格式。此类型具有 属性,对于其指数范围内的数字,如果任何 15 位或更少有效数字的十进制数字转换为 double
(使用舍入到最接近的数,并列到偶数) , 并将结果 double
转换回 15 位十进制数字,结果等于原始数字。
对于浮点数的默认格式,Java 生成的数字刚好足以 uniquely distinguish 浮点格式中的数字。
这两个属性的结果是,将具有 15 个或更少有效数字的十进制数字转换为 double
,然后使用默认格式将其转换回十进制将产生与原始数字相同的结果。它可能在某些方面有所不同。例如,原始数字可能有生成的数字没有的尾随零,例如“3.00”到“3”或“123.4500”到“123.45”。