sto*_*ito 6 java floating-point ieee-754
由于浮点数是基于 2 的数字系统,因此不可能0.24F直接表示为相同的数字,因此不可能在没有重复小数点的1/3十进制系统中表示,即或。1/3=0.3333...0.(3)
0.24F因此,当打印回十进制表示形式时,浮点数会0.23因四舍五入而发生变化:
println(0.24F) => 0.23999999463558197021484375
Run Code Online (Sandbox Code Playgroud)
while0.25F可以直接显示:
println(0.25F) => 0.25
Run Code Online (Sandbox Code Playgroud)
但是我如何确定一个数字可以完全表示呢?
isExactFloat(0.25F) ==> true
isExactFloat(0.24F) ==> false
Run Code Online (Sandbox Code Playgroud)
也许 Java API 已经有一些函数可以做到这一点?
UPD 这是一个代码,显示 [-4, 4] 范围内的浮点数及其内部表示:
public class FloatDestructure {
public static void main(String[] args) {
BigDecimal dec = BigDecimal.valueOf(-4000L, 3);
BigDecimal incr = BigDecimal.valueOf(1L, 3);
for (int i = 0; i <= 8000; i++) {
double dbl = dec.doubleValue();
floatDestuct(dbl, dec);
dec = dec.add(incr);
}
}
static boolean isExactFloat(double d) { return d == (float) d; }
static void floatDestuct(double val, BigDecimal dec) {
float value = (float) val;
int bits = Float.floatToIntBits(value);
int sign = bits >>> 31;
int exp = (bits >>> 23 & ((1 << 8) - 1)) - ((1 << 7) - 1);
int mantissa = bits & ((1 << 23) - 1);
float backToFloat = Float.intBitsToFloat((sign << 31) | (exp + ((1 << 7) - 1)) << 23 | mantissa);
boolean exactFloat = isExactFloat(val);
boolean exactFloatStr = Double.toString(value).length() <= 7;
System.out.println(dec.toString() + " " + (double) val + " " + (double) value + " sign: " + sign + " exp: " + exp + " mantissa: " + mantissa + " " + Integer.toBinaryString(mantissa) + " " + (double) backToFloat + " " + exactFloat + " " + exactFloatStr);
}
}
Run Code Online (Sandbox Code Playgroud)
当尾数为零时,浮点数绝对是精确的。但在其他情况下,比如-0.375或 则-1.625不太清楚。
我想在这里分享这个功能。
// Determine whether number is exactly representable in double.
// i.e., No rounding to an approximation during the conversion.
// Results are valid for numbers in the range [2^-24, 2^52].
public static boolean isExactFloat(double val) {
int exp2 = Math.getExponent(val);
int exp10 = (int) Math.floor(Math.log10(Math.abs(val)));
// check for any mismatch between the exact decimal and
// the round-trip representation.
int rightmost_bits = (52 - exp2) - (16 - exp10);
// create bitmask for rightmost bits
long mask = (1L << rightmost_bits) - 1;
// test if all rightmost bits are 0's (i.e., no rounding)
return (Double.doubleToLongBits(val) & mask) == 0;
}
Run Code Online (Sandbox Code Playgroud)
编辑:上面的函数可以更短
public static boolean isExactFloat(double val) {
int exp2 = Math.getExponent(val);
int exp10 = (int) Math.floor(Math.log10(Math.abs(val)));
long bits = Double.doubleToLongBits(val);
// test if at least n rightmost bits are 0's (i.e., no rounding)
return Long.numberOfTrailingZeros(bits) >= 36 - exp2 + exp10;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2086 次 |
| 最近记录: |