我只是在搞乱这种方法,看看它做了什么。我创建了一个值为3.14的变量,因为它在那个实例中出现了。
double n = 3.14;
System.out.println(Math.nextUp(n));
前面显示的是3.1400000000000006。
尝试使用3.1400000000000001,显示相同。
尝试333.33,显示333.33000000000004。
对于许多其他值,它会显示适当的值,例如73.6结果,73.60000000000001。
3.1400000000000000和3.1400000000000006之间的值会发生什么变化?为什么它会跳过某些值?我知道硬件相关的问题,但有时它的工作正常。即使已知无法进行精确操作,为什么这种方法包含在库中?它看起来很无用,因为它不能始终正常工作。
答案 0 :(得分:2)
Java中一个有用的技巧是使用ActionBar
和BigDecimal的new BigDecimal(double)
的精确度来显示double的确切值:
toString
输出:
import java.math.BigDecimal;
public class Test {
public static void main(String[] args) {
System.out.println(new BigDecimal(3.14));
System.out.println(new BigDecimal(3.1400000000000001));
System.out.println(new BigDecimal(3.1400000000000006));
}
}
存在有限数量的双精度数,因此只有实数的特定子集才是双精度的精确值。创建双字面值时,键入的十进制数字由最接近的值表示。当您输出一个double时,默认情况下,它会显示为输入时将舍入到它的最短小数部分。您需要执行我在程序中使用的BigDecimal技术,以查看确切的值。
在这种情况下,3.14和3.1400000000000001比任何其他双倍更接近3.140000000000000124344978758017532527446746826171875。上面的下一个完全可表示的数字是3.1400000000000005684341886080801486968994140625
答案 1 :(得分:1)
就像@jgreve提到的那样,由于使用了float和amp; java中的double primitives类型,这会导致所谓的舍入错误。另一方面,基本类型int是一个定点数,意味着它能够“适应”32位。双精度不是定点的,这意味着双重计算的结果必须经过舍入,以便适应其有限表示,这有时会导致(如您的情况所示)不一致的值。
有关详细信息,请参阅以下两个链接。
https://stackoverflow.com/a/322875/6012392
https://en.wikipedia.org/wiki/Double-precision_floating-point_format
解决方法可能是以下两个,它给出了第一个双重的“方向”。
double n = 1.4;
double x = 1.5;
System.out.println(Math.nextAfter(n, x));
或
double n = 1.4;
double next = n + Math.ulp(n);
System.out.println(next);
但是为了处理浮点值,建议使用BigDecimal
类
答案 2 :(得分:1)
浮点数以二进制形式存储:十进制表示仅供人类使用。
使用Rick Regan's decimal to floating point converter 3.14转换为:
11.001000111101011100001010001111010111000010100011111
和3.1400000000000006转换为
11.0010001111010111000010100011110101110000101001
这确实是下一个二进制数到53个有效位。