mirror of
https://github.com/konsoletyper/teavm.git
synced 2024-12-09 02:00:25 +08:00
classlib: improve accuracy of Double.toString
This commit is contained in:
parent
e2ee9f1dbb
commit
b2aae0634e
@ -21,6 +21,7 @@ public final class DoubleAnalyzer {
|
|||||||
static final int MAX_ABS_DEC_EXP = 330;
|
static final int MAX_ABS_DEC_EXP = 330;
|
||||||
public static final int DECIMAL_PRECISION = 18;
|
public static final int DECIMAL_PRECISION = 18;
|
||||||
public static final long DOUBLE_MAX_POS = 100000000000000000L;
|
public static final long DOUBLE_MAX_POS = 100000000000000000L;
|
||||||
|
private static final long MAX_MANTISSA = Long.divideUnsigned(-1, 10);
|
||||||
|
|
||||||
private DoubleAnalyzer() {
|
private DoubleAnalyzer() {
|
||||||
}
|
}
|
||||||
@ -54,13 +55,11 @@ public final class DoubleAnalyzer {
|
|||||||
int mantissaShift = 12 + binExponentCorrection;
|
int mantissaShift = 12 + binExponentCorrection;
|
||||||
|
|
||||||
long decMantissa = mulAndShiftRight(mantissa, mantissa10Table[decExponent + 1], mantissaShift);
|
long decMantissa = mulAndShiftRight(mantissa, mantissa10Table[decExponent + 1], mantissaShift);
|
||||||
if (decMantissa >= 1000000000000000000L) {
|
if (decMantissa <= MAX_MANTISSA) {
|
||||||
++decExponent;
|
while (Long.compareUnsigned(decMantissa, MAX_MANTISSA) <= 0) {
|
||||||
binExponentCorrection = exponent - exp10Table[decExponent + 1];
|
|
||||||
mantissaShift = 12 + binExponentCorrection;
|
|
||||||
decMantissa = mulAndShiftRight(mantissa, mantissa10Table[decExponent + 1], mantissaShift);
|
|
||||||
} else if (decMantissa <= 100000000000000000L) {
|
|
||||||
--decExponent;
|
--decExponent;
|
||||||
|
decMantissa = decMantissa * 10 + 9;
|
||||||
|
}
|
||||||
binExponentCorrection = exponent - exp10Table[decExponent + 1];
|
binExponentCorrection = exponent - exp10Table[decExponent + 1];
|
||||||
mantissaShift = 12 + binExponentCorrection;
|
mantissaShift = 12 + binExponentCorrection;
|
||||||
decMantissa = mulAndShiftRight(mantissa, mantissa10Table[decExponent + 1], mantissaShift);
|
decMantissa = mulAndShiftRight(mantissa, mantissa10Table[decExponent + 1], mantissaShift);
|
||||||
@ -72,18 +71,21 @@ public final class DoubleAnalyzer {
|
|||||||
|
|
||||||
var lowerPos = findLowerDistance(decMantissa, decMantissaLow);
|
var lowerPos = findLowerDistance(decMantissa, decMantissaLow);
|
||||||
var upperPos = findUpperDistance(decMantissa, decMantissaHi);
|
var upperPos = findUpperDistance(decMantissa, decMantissaHi);
|
||||||
if (lowerPos > upperPos) {
|
var posCmp = Long.compareUnsigned(lowerPos, upperPos);
|
||||||
decMantissa = (decMantissa / lowerPos) * lowerPos;
|
if (posCmp > 0) {
|
||||||
} else if (lowerPos < upperPos) {
|
decMantissa = Long.divideUnsigned(decMantissa, lowerPos) * lowerPos;
|
||||||
decMantissa = (decMantissa / upperPos) * upperPos + upperPos;
|
} else if (posCmp < 0) {
|
||||||
|
decMantissa = Long.divideUnsigned(decMantissa, upperPos) * upperPos + upperPos;
|
||||||
} else {
|
} else {
|
||||||
decMantissa = ((decMantissa + (upperPos / 2)) / upperPos) * upperPos;
|
decMantissa = Long.divideUnsigned(decMantissa + (upperPos / 2), upperPos) * upperPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (decMantissa >= 1000000000000000000L) {
|
if (Long.compareUnsigned(decMantissa, 1000000000000000000L) >= 0) {
|
||||||
|
do {
|
||||||
decExponent++;
|
decExponent++;
|
||||||
decMantissa /= 10;
|
decMantissa = Long.divideUnsigned(decMantissa, 10);
|
||||||
} else if (decMantissa < 100000000000000000L) {
|
} while (Long.compareUnsigned(decMantissa, 1000000000000000000L) >= 0);
|
||||||
|
} else if (Long.compareUnsigned(decMantissa, 100000000000000000L) < 0) {
|
||||||
decExponent--;
|
decExponent--;
|
||||||
decMantissa *= 10;
|
decMantissa *= 10;
|
||||||
}
|
}
|
||||||
@ -94,7 +96,9 @@ public final class DoubleAnalyzer {
|
|||||||
|
|
||||||
private static long findLowerDistance(long mantissa, long lower) {
|
private static long findLowerDistance(long mantissa, long lower) {
|
||||||
long pos = 1;
|
long pos = 1;
|
||||||
while (mantissa / (pos * 10) > lower / (pos * 10)) {
|
while (Long.compareUnsigned(
|
||||||
|
Long.divideUnsigned(mantissa, pos * 10),
|
||||||
|
Long.divideUnsigned(lower, pos * 10)) > 0) {
|
||||||
pos *= 10;
|
pos *= 10;
|
||||||
}
|
}
|
||||||
return pos;
|
return pos;
|
||||||
@ -102,7 +106,9 @@ public final class DoubleAnalyzer {
|
|||||||
|
|
||||||
private static long findUpperDistance(long mantissa, long upper) {
|
private static long findUpperDistance(long mantissa, long upper) {
|
||||||
long pos = 1;
|
long pos = 1;
|
||||||
while (mantissa / (pos * 10) < upper / (pos * 10)) {
|
while (Long.compareUnsigned(
|
||||||
|
Long.divideUnsigned(mantissa, pos * 10),
|
||||||
|
Long.divideUnsigned(upper, pos * 10)) < 0) {
|
||||||
pos *= 10;
|
pos *= 10;
|
||||||
}
|
}
|
||||||
return pos;
|
return pos;
|
||||||
@ -128,6 +134,7 @@ public final class DoubleAnalyzer {
|
|||||||
|
|
||||||
long c = (c3 << (32 + shift)) + (c2 << (16 + shift)) + (c1 << shift);
|
long c = (c3 << (32 + shift)) + (c2 << (16 + shift)) + (c1 << shift);
|
||||||
cm += c0 << 16;
|
cm += c0 << 16;
|
||||||
|
// TODO: removing this gives better result in random tests, however toString(1.0) gives '0.5'
|
||||||
if (((cm >>> (31 - shift)) & 1) != 0) {
|
if (((cm >>> (31 - shift)) & 1) != 0) {
|
||||||
++c;
|
++c;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user