Java 0 到 1 之间的值的浮点精度
Java Float Precision for values between 0 and 1
我将 0 到 1 之间的值存储为浮点数。
我知道可区分浮点数之间的增量越小,浮点数越接近 0。因此,我认为在我的情况下精度非常高(因为最高可能的浮点数是 1..)。比较其中两个浮点数时,我必须考虑的 epsilon 有多大?即 1.0f 与小于 1.0f 的最大可表示浮点数之间的差距有多大?很抱歉,如果这个问题看起来太过 broad/general 但我找不到答案 :-(。
谢谢
你可以使用函数java.lang.Math.nextAfter(float start, double direction)
来帮助你。
在您的情况下,使用 nextAfter(1.0f, 0.0)
来调用它。这里我们将 direction
设置为小于您的起始数字,因此它将搜索 "backwards"。结果 float
就是你的答案。
因为这个函数还有一个重载,为 start
使用 double
,请小心使用 1.0f
来表示 float
文字。
要获得浮点值或双精度值的分辨率单位,您可以使用 Math.ulp(x)
,这将给出 x
和下一个可表示值之间的差异。注意:1
是 1.0
之前值的两倍差距
float f = 1.0f, f_1 = Math.nextDown(f);
double d = 1.0, d_1 = Math.nextDown(d);
int f_1i = Float.floatToRawIntBits(f_1);
System.out.println("f_1=" + f_1 + " f_1i=" + Integer.toHexString(f_1i) + " eps=" + Math.ulp(f_1) + " nextUp=" + Math.nextUp(f_1));
int fi = Float.floatToRawIntBits(f);
System.out.println("f=" + f + " fi=" + Integer.toHexString(fi) + " eps=" + Math.ulp(f) + " nextUp=" + Math.nextUp(f));
long d_1i = Double.doubleToRawLongBits(d_1);
System.out.println("d_1=" + d_1 + " d_1i=" + Long.toHexString(d_1i) + " eps=" + Math.ulp(d_1) + " nextUp=" + Math.nextUp(d_1));
long di = Double.doubleToRawLongBits(d);
System.out.println("d=" + d + " di=" + Long.toHexString(di) + " eps=" + Math.ulp(d) + " nextUp=" + Math.nextUp(d));
打印
f_1=0.99999994 f_1i=3f7fffff eps=5.9604645E-8 nextUp=1.0
f=1.0 fi=3f800000 eps=1.1920929E-7 nextUp=1.0000001
d_1=0.9999999999999999 d_1i=3fefffffffffffff eps=1.1102230246251565E-16 nextUp=1.0
d=1.0 di=3ff0000000000000 eps=2.220446049250313E-16 nextUp=1.0000000000000002
您还可以通过查看原始整数表示对可表示值进行算术运算。
例如Math.nextUp
public static double nextUp(double d) {
if( Double.isNaN(d) || d == Double.POSITIVE_INFINITY)
return d;
else {
d += 0.0d;
return Double.longBitsToDouble(Double.doubleToRawLongBits(d) +
((d >= 0.0d)?+1L:-1L));
}
}
BTW d += 0.0d
将 -0.0
变成 +0.0
还有
System.out.println(Math.ulp(Double.NEGATIVE_INFINITY));
打印
Infinity
我将 0 到 1 之间的值存储为浮点数。 我知道可区分浮点数之间的增量越小,浮点数越接近 0。因此,我认为在我的情况下精度非常高(因为最高可能的浮点数是 1..)。比较其中两个浮点数时,我必须考虑的 epsilon 有多大?即 1.0f 与小于 1.0f 的最大可表示浮点数之间的差距有多大?很抱歉,如果这个问题看起来太过 broad/general 但我找不到答案 :-(。 谢谢
你可以使用函数java.lang.Math.nextAfter(float start, double direction)
来帮助你。
在您的情况下,使用 nextAfter(1.0f, 0.0)
来调用它。这里我们将 direction
设置为小于您的起始数字,因此它将搜索 "backwards"。结果 float
就是你的答案。
因为这个函数还有一个重载,为 start
使用 double
,请小心使用 1.0f
来表示 float
文字。
要获得浮点值或双精度值的分辨率单位,您可以使用 Math.ulp(x)
,这将给出 x
和下一个可表示值之间的差异。注意:1
是 1.0
float f = 1.0f, f_1 = Math.nextDown(f);
double d = 1.0, d_1 = Math.nextDown(d);
int f_1i = Float.floatToRawIntBits(f_1);
System.out.println("f_1=" + f_1 + " f_1i=" + Integer.toHexString(f_1i) + " eps=" + Math.ulp(f_1) + " nextUp=" + Math.nextUp(f_1));
int fi = Float.floatToRawIntBits(f);
System.out.println("f=" + f + " fi=" + Integer.toHexString(fi) + " eps=" + Math.ulp(f) + " nextUp=" + Math.nextUp(f));
long d_1i = Double.doubleToRawLongBits(d_1);
System.out.println("d_1=" + d_1 + " d_1i=" + Long.toHexString(d_1i) + " eps=" + Math.ulp(d_1) + " nextUp=" + Math.nextUp(d_1));
long di = Double.doubleToRawLongBits(d);
System.out.println("d=" + d + " di=" + Long.toHexString(di) + " eps=" + Math.ulp(d) + " nextUp=" + Math.nextUp(d));
打印
f_1=0.99999994 f_1i=3f7fffff eps=5.9604645E-8 nextUp=1.0
f=1.0 fi=3f800000 eps=1.1920929E-7 nextUp=1.0000001
d_1=0.9999999999999999 d_1i=3fefffffffffffff eps=1.1102230246251565E-16 nextUp=1.0
d=1.0 di=3ff0000000000000 eps=2.220446049250313E-16 nextUp=1.0000000000000002
您还可以通过查看原始整数表示对可表示值进行算术运算。
例如Math.nextUp
public static double nextUp(double d) {
if( Double.isNaN(d) || d == Double.POSITIVE_INFINITY)
return d;
else {
d += 0.0d;
return Double.longBitsToDouble(Double.doubleToRawLongBits(d) +
((d >= 0.0d)?+1L:-1L));
}
}
BTW d += 0.0d
将 -0.0
变成 +0.0
还有
System.out.println(Math.ulp(Double.NEGATIVE_INFINITY));
打印
Infinity