mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-23 00:24:11 -08:00
Add multiplier support to DecimalFormat
This commit is contained in:
parent
815b90459a
commit
fe7ae9f052
|
@ -15,6 +15,8 @@
|
|||
*/
|
||||
package org.teavm.classlib.java.text;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.text.DecimalFormatSymbols;
|
||||
import org.teavm.classlib.impl.unicode.CLDRHelper;
|
||||
import org.teavm.classlib.java.lang.TArithmeticException;
|
||||
|
@ -36,11 +38,11 @@ public class TDecimalFormat extends TNumberFormat {
|
|||
private static final double[] POWM10_FRAC_ARRAY = { 1E-1, 1E-2, 1E-4, 1E-8, 1E-16, 1E-32, 1E-64, 1E-128, 1E-256 };
|
||||
private static final int DOUBLE_MAX_EXPONENT = 308;
|
||||
TDecimalFormatSymbols symbols;
|
||||
private String positivePrefix;
|
||||
private String negativePrefix;
|
||||
private String positiveSuffix;
|
||||
private String negativeSuffix;
|
||||
private int multiplier;
|
||||
private String positivePrefix = "";
|
||||
private String negativePrefix = "-";
|
||||
private String positiveSuffix = "";
|
||||
private String negativeSuffix = "";
|
||||
private int multiplier = 1;
|
||||
private int groupingSize;
|
||||
private boolean decimalSeparatorAlwaysShown;
|
||||
private boolean parseBigDecimal;
|
||||
|
@ -181,6 +183,31 @@ public class TDecimalFormat extends TNumberFormat {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringBuffer format(Object object, StringBuffer buffer, TFieldPosition field) {
|
||||
if (object instanceof BigDecimal) {
|
||||
return format((BigDecimal)object, buffer, field);
|
||||
} else if (object instanceof BigInteger) {
|
||||
return format((BigInteger)object, buffer, field);
|
||||
} else {
|
||||
return super.format(object, buffer, field);
|
||||
}
|
||||
}
|
||||
|
||||
private StringBuffer format(BigInteger value, StringBuffer buffer, TFieldPosition field) {
|
||||
return format(new BigDecimal(value), buffer, field);
|
||||
}
|
||||
|
||||
private StringBuffer format(BigDecimal value, StringBuffer buffer,
|
||||
@SuppressWarnings("unused") TFieldPosition field) {
|
||||
if (exponentDigits > 0) {
|
||||
formatExponent(value, buffer);
|
||||
} else {
|
||||
formatRegular(value, buffer);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringBuffer format(long value, StringBuffer buffer, TFieldPosition field) {
|
||||
if (exponentDigits > 0) {
|
||||
|
@ -193,11 +220,18 @@ public class TDecimalFormat extends TNumberFormat {
|
|||
|
||||
@Override
|
||||
public StringBuffer format(double value, StringBuffer buffer, TFieldPosition field) {
|
||||
MantissaAndExponent me = getMantissaAndExponent(value);
|
||||
if (exponentDigits > 0) {
|
||||
formatExponent(me.mantissa, me.exponent, buffer);
|
||||
if (Double.isNaN(value)) {
|
||||
buffer.append(positivePrefix).append(symbols.getNaN()).append(positiveSuffix);
|
||||
} else if (Double.isInfinite(value)) {
|
||||
buffer.append(value > 0 ? positivePrefix : negativePrefix).append(symbols.getInfinity())
|
||||
.append(value > 0 ? positiveSuffix : negativeSuffix);
|
||||
} else {
|
||||
formatRegular(me.mantissa, me.exponent, buffer);
|
||||
MantissaAndExponent me = getMantissaAndExponent(value);
|
||||
if (exponentDigits > 0) {
|
||||
formatExponent(me.mantissa, me.exponent, buffer);
|
||||
} else {
|
||||
formatRegular(me.mantissa, me.exponent, buffer);
|
||||
}
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
@ -217,6 +251,22 @@ public class TDecimalFormat extends TNumberFormat {
|
|||
int visibleExponent = fastLn10(mantissa);
|
||||
int mantissaLength = visibleExponent + 1;
|
||||
|
||||
if (multiplier != 1) {
|
||||
int multiplierDigits = fastLn10(multiplier);
|
||||
int tenMultiplier = POW10_INT_ARRAY[multiplierDigits];
|
||||
if (tenMultiplier == multiplier) {
|
||||
exponent += multiplierDigits;
|
||||
} else if (mantissa >= Long.MAX_VALUE / multiplier || mantissa <= Long.MIN_VALUE / multiplier) {
|
||||
formatExponent(new BigDecimal(BigInteger.valueOf(mantissa), mantissaLength - exponent), buffer);
|
||||
return;
|
||||
} else {
|
||||
mantissa *= multiplier;
|
||||
positive = mantissa >= 0;
|
||||
visibleExponent = fastLn10(mantissa);
|
||||
mantissaLength = visibleExponent + 1;
|
||||
}
|
||||
}
|
||||
|
||||
int significantSize = getMinimumIntegerDigits() + getMaximumFractionDigits();
|
||||
int exponentMultiplier = getMaximumIntegerDigits() - getMinimumIntegerDigits() + 1;
|
||||
if (exponentMultiplier > 1) {
|
||||
|
@ -240,7 +290,7 @@ public class TDecimalFormat extends TNumberFormat {
|
|||
int exponentPos = Math.max(visibleExponent, 0);
|
||||
for (int i = mantissaLength - 1; i >= exponentPos; --i) {
|
||||
long mantissaDigitMask = POW10_ARRAY[i];
|
||||
buffer.append(Character.forDigit(Math.abs((int)(mantissa / mantissaDigitMask)), 10));
|
||||
buffer.append(forDigit(Math.abs((int)(mantissa / mantissaDigitMask))));
|
||||
mantissa %= mantissaDigitMask;
|
||||
}
|
||||
for (int i = exponentPos - 1; i >= visibleExponent; --i) {
|
||||
|
@ -256,7 +306,7 @@ public class TDecimalFormat extends TNumberFormat {
|
|||
int count = 0;
|
||||
for (int i = visibleExponent - 1; i >= limit; --i) {
|
||||
long mantissaDigitMask = POW10_ARRAY[i];
|
||||
buffer.append(Character.forDigit(Math.abs((int)(mantissa / mantissaDigitMask)), 10));
|
||||
buffer.append(forDigit(Math.abs((int)(mantissa / mantissaDigitMask))));
|
||||
mantissa %= mantissaDigitMask;
|
||||
++count;
|
||||
if (mantissa == 0) {
|
||||
|
@ -276,7 +326,7 @@ public class TDecimalFormat extends TNumberFormat {
|
|||
int exponentLength = Math.max(exponentDigits, fastLn10(exponent) + 1);
|
||||
for (int i = exponentLength - 1; i >= 0; --i) {
|
||||
int exponentDigit = POW10_INT_ARRAY[i];
|
||||
buffer.append(Character.forDigit(exponent / exponentDigit, 10));
|
||||
buffer.append(forDigit(exponent / exponentDigit));
|
||||
exponent %= exponentDigit;
|
||||
}
|
||||
|
||||
|
@ -293,6 +343,18 @@ public class TDecimalFormat extends TNumberFormat {
|
|||
int mantissaLength = fastLn10(mantissa) + 1;
|
||||
++exponent;
|
||||
|
||||
int multiplierDigits = fastLn10(multiplier);
|
||||
int tenMultiplier = POW10_INT_ARRAY[multiplierDigits];
|
||||
if (tenMultiplier == multiplier) {
|
||||
exponent += multiplierDigits;
|
||||
} else if (mantissa >= Long.MAX_VALUE / multiplier || mantissa <= Long.MIN_VALUE / multiplier) {
|
||||
formatRegular(new BigDecimal(BigInteger.valueOf(mantissa), mantissaLength - exponent), buffer);
|
||||
return;
|
||||
} else {
|
||||
mantissa *= multiplier;
|
||||
mantissaLength = fastLn10(mantissa) + 1;
|
||||
}
|
||||
|
||||
// Apply rounding if necessary
|
||||
int roundingPos = exponent + getMaximumFractionDigits();
|
||||
if (roundingPos < 0) {
|
||||
|
@ -320,7 +382,7 @@ public class TDecimalFormat extends TNumberFormat {
|
|||
int mantissaDigit = mantissaLength - 1;
|
||||
for (int i = 0; i < significantIntDigits; ++i) {
|
||||
long mantissaDigitMask = POW10_ARRAY[mantissaDigit--];
|
||||
buffer.append(Character.forDigit(Math.abs((int)(mantissa / mantissaDigitMask)), 10));
|
||||
buffer.append(forDigit(Math.abs((int)(mantissa / mantissaDigitMask))));
|
||||
mantissa %= mantissaDigitMask;
|
||||
if (groupingSize > 0 && digitPos % groupingSize == 0 && digitPos > 0) {
|
||||
buffer.append(symbols.getGroupingSeparator());
|
||||
|
@ -368,7 +430,7 @@ public class TDecimalFormat extends TNumberFormat {
|
|||
}
|
||||
++digitPos;
|
||||
long mantissaDigitMask = POW10_ARRAY[mantissaDigit];
|
||||
buffer.append(Character.forDigit(Math.abs((int)(mantissa / mantissaDigitMask)), 10));
|
||||
buffer.append(forDigit(Math.abs((int)(mantissa / mantissaDigitMask))));
|
||||
mantissa %= mantissaDigitMask;
|
||||
mantissaDigit--;
|
||||
}
|
||||
|
@ -388,6 +450,197 @@ public class TDecimalFormat extends TNumberFormat {
|
|||
}
|
||||
}
|
||||
|
||||
private void formatExponent(BigDecimal value, StringBuffer buffer) {
|
||||
if (multiplier != 1) {
|
||||
value = value.multiply(BigDecimal.valueOf(multiplier));
|
||||
}
|
||||
boolean positive = value.compareTo(BigDecimal.ZERO) >= 0;
|
||||
int mantissaLength = value.precision();
|
||||
int visibleExponent = mantissaLength - 1;
|
||||
int exponent = visibleExponent - value.scale();
|
||||
BigInteger mantissa = value.unscaledValue();
|
||||
|
||||
int significantSize = getMinimumIntegerDigits() + getMaximumFractionDigits();
|
||||
int exponentMultiplier = getMaximumIntegerDigits() - getMinimumIntegerDigits() + 1;
|
||||
if (exponentMultiplier > 1) {
|
||||
int delta = exponent - (exponent / exponentMultiplier) * exponentMultiplier;
|
||||
exponent -= delta;
|
||||
visibleExponent -= delta;
|
||||
} else {
|
||||
exponent -= getMinimumIntegerDigits() - 1;
|
||||
visibleExponent -= getMinimumIntegerDigits() - 1;
|
||||
}
|
||||
|
||||
if (significantSize < 0) {
|
||||
mantissa = BigInteger.ZERO;
|
||||
} else if (significantSize < mantissaLength) {
|
||||
mantissa = applyRounding(mantissa, mantissaLength, significantSize);
|
||||
}
|
||||
|
||||
// Append pattern prefix
|
||||
buffer.append(positive ? positivePrefix : negativePrefix);
|
||||
|
||||
int exponentPos = Math.max(visibleExponent, 0);
|
||||
BigInteger mantissaDigitMask = pow10(BigInteger.ONE, mantissaLength - 1);
|
||||
for (int i = mantissaLength - 1; i >= exponentPos; --i) {
|
||||
BigInteger[] parts = mantissa.divideAndRemainder(mantissaDigitMask);
|
||||
buffer.append(forDigit(Math.abs(parts[0].intValue())));
|
||||
mantissa = parts[1];
|
||||
mantissaDigitMask = mantissaDigitMask.divide(BigInteger.TEN);
|
||||
}
|
||||
for (int i = exponentPos - 1; i >= visibleExponent; --i) {
|
||||
buffer.append('0');
|
||||
}
|
||||
|
||||
significantSize -= mantissaLength - visibleExponent;
|
||||
int requiredSize = significantSize - (getMaximumFractionDigits() - getMinimumFractionDigits());
|
||||
if (requiredSize > 0 || (!mantissa.equals(BigInteger.ZERO) && significantSize > 0)) {
|
||||
buffer.append(symbols.getDecimalSeparator());
|
||||
|
||||
int limit = Math.max(0, visibleExponent - significantSize);
|
||||
int count = 0;
|
||||
for (int i = visibleExponent - 1; i >= limit; --i) {
|
||||
BigInteger[] parts = mantissa.divideAndRemainder(mantissaDigitMask);
|
||||
buffer.append(forDigit(Math.abs(parts[0].intValue())));
|
||||
mantissa = parts[1];
|
||||
++count;
|
||||
if (mantissa.equals(BigInteger.ZERO)) {
|
||||
break;
|
||||
}
|
||||
mantissaDigitMask = mantissaDigitMask.divide(BigInteger.TEN);
|
||||
}
|
||||
while (count++ < requiredSize) {
|
||||
buffer.append('0');
|
||||
}
|
||||
}
|
||||
|
||||
buffer.append(symbols.getExponentSeparator());
|
||||
if (exponent < 0) {
|
||||
exponent = -exponent;
|
||||
buffer.append(symbols.getMinusSign());
|
||||
}
|
||||
int exponentLength = Math.max(exponentDigits, fastLn10(exponent) + 1);
|
||||
for (int i = exponentLength - 1; i >= 0; --i) {
|
||||
int exponentDigit = POW10_INT_ARRAY[i];
|
||||
buffer.append(forDigit(exponent / exponentDigit));
|
||||
exponent %= exponentDigit;
|
||||
}
|
||||
|
||||
// Add suffix
|
||||
if (positive) {
|
||||
buffer.append(positiveSuffix != null ? positiveSuffix : "");
|
||||
} else {
|
||||
buffer.append(negativeSuffix != null ? negativeSuffix : positiveSuffix != null ? positiveSuffix : "");
|
||||
}
|
||||
}
|
||||
|
||||
private void formatRegular(BigDecimal value, StringBuffer buffer) {
|
||||
if (multiplier != 1) {
|
||||
value = value.multiply(BigDecimal.valueOf(multiplier));
|
||||
}
|
||||
BigInteger mantissa = value.unscaledValue();
|
||||
boolean positive = mantissa.compareTo(BigInteger.ZERO) >= 0;
|
||||
int mantissaLength = value.precision();
|
||||
int exponent = value.precision() - value.scale();
|
||||
|
||||
// Apply rounding if necessary
|
||||
int roundingPos = exponent + getMaximumFractionDigits();
|
||||
if (roundingPos < 0) {
|
||||
mantissa = BigInteger.ZERO;
|
||||
} else if (roundingPos < mantissaLength) {
|
||||
mantissa = applyRounding(mantissa, mantissaLength, roundingPos);
|
||||
}
|
||||
|
||||
// Append pattern prefix
|
||||
buffer.append(positive ? positivePrefix : negativePrefix);
|
||||
|
||||
// Add insignificant integer zeros
|
||||
int intLength = Math.max(0, exponent);
|
||||
int digitPos = Math.max(intLength, getMinimumIntegerDigits()) - 1;
|
||||
for (int i = getMinimumIntegerDigits() - 1; i >= intLength; --i) {
|
||||
buffer.append('0');
|
||||
if (groupingSize > 0 && digitPos % groupingSize == 0 && digitPos > 0) {
|
||||
buffer.append(symbols.getGroupingSeparator());
|
||||
}
|
||||
--digitPos;
|
||||
}
|
||||
|
||||
// Add significant integer digits
|
||||
int significantIntDigits = Math.min(mantissaLength, intLength);
|
||||
BigInteger mantissaDigitMask = pow10(BigInteger.ONE, mantissaLength - 1);
|
||||
for (int i = 0; i < significantIntDigits; ++i) {
|
||||
BigInteger[] parts = mantissa.divideAndRemainder(mantissaDigitMask);
|
||||
buffer.append(forDigit(Math.abs(parts[0].intValue())));
|
||||
mantissa = parts[1];
|
||||
if (groupingSize > 0 && digitPos % groupingSize == 0 && digitPos > 0) {
|
||||
buffer.append(symbols.getGroupingSeparator());
|
||||
}
|
||||
--digitPos;
|
||||
--mantissaLength;
|
||||
mantissaDigitMask = mantissaDigitMask.divide(BigInteger.TEN);
|
||||
}
|
||||
|
||||
// Add significant integer zeros
|
||||
intLength -= significantIntDigits;
|
||||
for (int i = 0; i < intLength; ++i) {
|
||||
buffer.append('0');
|
||||
if (groupingSize > 0 && digitPos % groupingSize == 0 && digitPos > 0) {
|
||||
buffer.append(symbols.getGroupingSeparator());
|
||||
}
|
||||
--digitPos;
|
||||
}
|
||||
|
||||
if (mantissa.equals(BigInteger.ZERO)) {
|
||||
if (getMinimumFractionDigits() == 0) {
|
||||
if (isDecimalSeparatorAlwaysShown()) {
|
||||
buffer.append(symbols.getDecimalSeparator());
|
||||
}
|
||||
} else {
|
||||
buffer.append(symbols.getDecimalSeparator());
|
||||
for (int i = 0; i < getMinimumFractionDigits(); ++i) {
|
||||
buffer.append('0');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
buffer.append(symbols.getDecimalSeparator());
|
||||
|
||||
// Add significant fractional zeros
|
||||
int fracZeros = Math.min(getMaximumFractionDigits(), Math.max(0, -exponent));
|
||||
digitPos = 0;
|
||||
for (int i = 0; i < fracZeros; ++i) {
|
||||
++digitPos;
|
||||
buffer.append('0');
|
||||
}
|
||||
|
||||
// Add significant fractional digits
|
||||
int significantFracDigits = Math.min(getMaximumFractionDigits() - digitPos, mantissaLength);
|
||||
for (int i = 0; i < significantFracDigits; ++i) {
|
||||
if (mantissa.equals(BigInteger.ZERO)) {
|
||||
break;
|
||||
}
|
||||
++digitPos;
|
||||
BigInteger[] parts = mantissa.divideAndRemainder(mantissaDigitMask);
|
||||
buffer.append(forDigit(Math.abs(parts[0].intValue())));
|
||||
mantissa = parts[1];
|
||||
--mantissaLength;
|
||||
mantissaDigitMask = mantissaDigitMask.divide(BigInteger.TEN);
|
||||
}
|
||||
|
||||
// Add insignificant fractional zeros
|
||||
for (int i = digitPos; i < getMinimumFractionDigits(); ++i) {
|
||||
++digitPos;
|
||||
buffer.append('0');
|
||||
}
|
||||
}
|
||||
|
||||
// Add suffix
|
||||
if (positive) {
|
||||
buffer.append(positiveSuffix != null ? positiveSuffix : "");
|
||||
} else {
|
||||
buffer.append(negativeSuffix != null ? negativeSuffix : positiveSuffix != null ? positiveSuffix : "");
|
||||
}
|
||||
}
|
||||
|
||||
private long applyRounding(long mantissa, int mantissaLength, int exponent) {
|
||||
long rounding = POW10_ARRAY[mantissaLength - exponent];
|
||||
long signedRounding = mantissa > 0 ? rounding : -rounding;
|
||||
|
@ -444,6 +697,65 @@ public class TDecimalFormat extends TNumberFormat {
|
|||
return mantissa;
|
||||
}
|
||||
|
||||
private BigInteger applyRounding(BigInteger mantissa, int mantissaLength, int exponent) {
|
||||
BigInteger rounding = pow10(BigInteger.ONE, mantissaLength - exponent);
|
||||
BigInteger signedRounding = mantissa.compareTo(BigInteger.ZERO) >= 0 ? rounding : rounding.negate();
|
||||
switch (getRoundingMode()) {
|
||||
case CEILING:
|
||||
mantissa = mantissa.divide(rounding).multiply(rounding);
|
||||
if (mantissa.compareTo(BigInteger.ZERO) >= 0) {
|
||||
mantissa = mantissa.add(rounding);
|
||||
}
|
||||
break;
|
||||
case FLOOR:
|
||||
mantissa = mantissa.divide(rounding).multiply(rounding);
|
||||
if (mantissa.compareTo(BigInteger.ZERO) <= 0) {
|
||||
mantissa = mantissa.subtract(rounding);
|
||||
}
|
||||
break;
|
||||
case UP:
|
||||
mantissa = mantissa.divide(rounding).multiply(rounding).add(signedRounding);
|
||||
break;
|
||||
case DOWN:
|
||||
mantissa = mantissa.divide(rounding).multiply(rounding);
|
||||
break;
|
||||
case UNNECESSARY:
|
||||
if (mantissa.remainder(rounding).equals(BigInteger.ZERO)) {
|
||||
throw new TArithmeticException(TString.wrap("Can't avoid rounding"));
|
||||
}
|
||||
break;
|
||||
case HALF_DOWN:
|
||||
if (mantissa.remainder(rounding).equals(signedRounding.divide(BigInteger.valueOf(2)))) {
|
||||
mantissa = mantissa.divide(rounding).multiply(rounding);
|
||||
} else {
|
||||
mantissa = mantissa.add(signedRounding.divide(BigInteger.valueOf(2)))
|
||||
.divide(rounding).multiply(rounding);
|
||||
}
|
||||
break;
|
||||
case HALF_UP:
|
||||
if (mantissa.remainder(rounding).equals(signedRounding.divide(BigInteger.valueOf(2)))) {
|
||||
mantissa = mantissa.divide(rounding).multiply(rounding).add(signedRounding);
|
||||
} else {
|
||||
mantissa = mantissa.add(signedRounding.divide(BigInteger.valueOf(2)))
|
||||
.divide(rounding).multiply(rounding);
|
||||
}
|
||||
break;
|
||||
case HALF_EVEN: {
|
||||
if (mantissa.remainder(rounding).equals(signedRounding.divide(BigInteger.valueOf(2)))) {
|
||||
mantissa = mantissa.divide(rounding).multiply(rounding);
|
||||
if (!mantissa.divide(rounding).remainder(BigInteger.valueOf(2)).equals(BigInteger.ZERO)) {
|
||||
mantissa = mantissa.add(signedRounding);
|
||||
}
|
||||
} else {
|
||||
mantissa = mantissa.add(signedRounding.divide(BigInteger.valueOf(2)))
|
||||
.divide(rounding).multiply(rounding);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return mantissa;
|
||||
}
|
||||
|
||||
private int fastLn10(long value) {
|
||||
int result = 0;
|
||||
if (value >= 0) {
|
||||
|
@ -513,6 +825,18 @@ public class TDecimalFormat extends TNumberFormat {
|
|||
return result;
|
||||
}
|
||||
|
||||
private BigInteger pow10(BigInteger value, int power) {
|
||||
BigInteger digit = BigInteger.TEN;
|
||||
while (power != 0) {
|
||||
if ((power & 1) != 0) {
|
||||
value = value.multiply(digit);
|
||||
}
|
||||
digit = digit.multiply(digit);
|
||||
power >>>= 1;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private MantissaAndExponent getMantissaAndExponent(double value) {
|
||||
long mantissaPattern = POW10_ARRAY[17];
|
||||
int exp = 0;
|
||||
|
@ -554,6 +878,10 @@ public class TDecimalFormat extends TNumberFormat {
|
|||
return new MantissaAndExponent(positive ? mantissa : -mantissa, exp);
|
||||
}
|
||||
|
||||
private char forDigit(int n) {
|
||||
return (char)(symbols.getZeroDigit() + n);
|
||||
}
|
||||
|
||||
static class MantissaAndExponent {
|
||||
long mantissa;
|
||||
int exponent;
|
||||
|
|
|
@ -20,8 +20,8 @@ package org.teavm.classlib.java.text;
|
|||
* @author Alexey Andreev
|
||||
*/
|
||||
class TDecimalFormatParser {
|
||||
private String positivePrefix;
|
||||
private String positiveSuffix;
|
||||
private String positivePrefix = "";
|
||||
private String positiveSuffix = "";
|
||||
private String negativePrefix;
|
||||
private String negativeSuffix;
|
||||
private int groupSize;
|
||||
|
|
|
@ -744,6 +744,9 @@ function Long_rem(a, b) {
|
|||
return Long_divRem(a, b)[1];
|
||||
}
|
||||
function Long_divRem(a, b) {
|
||||
if (b.lo == 0 && b.hi == 0) {
|
||||
throw new Error("Division by zero");
|
||||
}
|
||||
var positive = Long_isNegative(a) === Long_isNegative(b);
|
||||
if (Long_isNegative(a)) {
|
||||
a = Long_neg(a);
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package org.teavm.classlib.java.text;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.math.RoundingMode;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.DecimalFormatSymbols;
|
||||
|
@ -122,6 +124,15 @@ public class DecimalFormatTest {
|
|||
assertEquals("24", format.format(23.7));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formatsBigIntegerPart() {
|
||||
DecimalFormat format = createFormat("00");
|
||||
assertEquals("02", format.format(new BigInteger("2")));
|
||||
assertEquals("23", format.format(new BigInteger("23")));
|
||||
assertEquals("23", format.format(new BigDecimal("23.2")));
|
||||
assertEquals("24", format.format(new BigDecimal("23.7")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formatsNumber() {
|
||||
DecimalFormat format = createFormat("0.0");
|
||||
|
@ -144,6 +155,28 @@ public class DecimalFormatTest {
|
|||
assertEquals("0.00000000000000000000000023", format.format(23E-26));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formatsBigNumber() {
|
||||
DecimalFormat format = createFormat("0.0");
|
||||
assertEquals("23.0", format.format(BigInteger.valueOf(23)));
|
||||
assertEquals("23.2", format.format(new BigDecimal("23.2")));
|
||||
assertEquals("23.2", format.format(new BigDecimal("23.23")));
|
||||
assertEquals("23.3", format.format(new BigDecimal("23.27")));
|
||||
assertEquals("0.0", format.format(new BigDecimal("0.0001")));
|
||||
|
||||
format = createFormat("00000000000000000000000000.0");
|
||||
assertEquals("00000000000000000000000023.0", format.format(new BigInteger("23")));
|
||||
assertEquals("00002300000000000000000000.0", format.format(new BigInteger("2300000000000000000000")));
|
||||
assertEquals("23000000000000000000000000.0", format.format(new BigInteger("23000000000000000000000000")));
|
||||
|
||||
format = createFormat("0.00000000000000000000000000");
|
||||
assertEquals("23.00000000000000000000000000", format.format(new BigInteger("23")));
|
||||
assertEquals("0.23000000000000000000000000", format.format(new BigDecimal("0.23")));
|
||||
assertEquals("0.00230000000000000000000000", format.format(new BigDecimal("0.0023")));
|
||||
assertEquals("0.00000000000000000000230000", format.format(new BigDecimal("0.0000000000000000000023")));
|
||||
assertEquals("0.00000000000000000000000023", format.format(new BigDecimal("0.00000000000000000000000023")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formatsFractionalPart() {
|
||||
DecimalFormat format = createFormat("0.0000####");
|
||||
|
@ -216,6 +249,59 @@ public class DecimalFormatTest {
|
|||
assertEquals("-4", format.format(-3.5));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bigRoundingWorks() {
|
||||
DecimalFormat format = createFormat("0");
|
||||
|
||||
format.setRoundingMode(RoundingMode.UP);
|
||||
assertEquals("3", format.format(new BigDecimal("2.3")));
|
||||
assertEquals("3", format.format(new BigDecimal("2.7")));
|
||||
assertEquals("-3", format.format(new BigDecimal("-2.3")));
|
||||
assertEquals("-3", format.format(new BigDecimal("-2.7")));
|
||||
|
||||
format.setRoundingMode(RoundingMode.DOWN);
|
||||
assertEquals("2", format.format(new BigDecimal("2.3")));
|
||||
assertEquals("2", format.format(new BigDecimal("2.7")));
|
||||
assertEquals("-2", format.format(new BigDecimal("-2.3")));
|
||||
assertEquals("-2", format.format(new BigDecimal("-2.7")));
|
||||
|
||||
format.setRoundingMode(RoundingMode.FLOOR);
|
||||
assertEquals("2", format.format(new BigDecimal("2.3")));
|
||||
assertEquals("2", format.format(new BigDecimal("2.7")));
|
||||
assertEquals("-3", format.format(new BigDecimal("-2.3")));
|
||||
assertEquals("-3", format.format(new BigDecimal("-2.7")));
|
||||
|
||||
format.setRoundingMode(RoundingMode.CEILING);
|
||||
assertEquals("3", format.format(new BigDecimal("2.3")));
|
||||
assertEquals("3", format.format(new BigDecimal("2.7")));
|
||||
assertEquals("-2", format.format(new BigDecimal("-2.3")));
|
||||
assertEquals("-2", format.format(new BigDecimal("-2.7")));
|
||||
|
||||
format.setRoundingMode(RoundingMode.HALF_DOWN);
|
||||
assertEquals("2", format.format(new BigDecimal("2.3")));
|
||||
assertEquals("3", format.format(new BigDecimal("2.7")));
|
||||
assertEquals("2", format.format(new BigDecimal("2.5")));
|
||||
assertEquals("3", format.format(new BigDecimal("3.5")));
|
||||
assertEquals("-2", format.format(new BigDecimal("-2.5")));
|
||||
assertEquals("-3", format.format(new BigDecimal("-3.5")));
|
||||
|
||||
format.setRoundingMode(RoundingMode.HALF_UP);
|
||||
assertEquals("2", format.format(new BigDecimal("2.3")));
|
||||
assertEquals("3", format.format(new BigDecimal("2.7")));
|
||||
assertEquals("3", format.format(new BigDecimal("2.5")));
|
||||
assertEquals("4", format.format(new BigDecimal("3.5")));
|
||||
assertEquals("-3", format.format(new BigDecimal("-2.5")));
|
||||
assertEquals("-4", format.format(new BigDecimal("-3.5")));
|
||||
|
||||
format.setRoundingMode(RoundingMode.HALF_EVEN);
|
||||
assertEquals("2", format.format(new BigDecimal("2.3")));
|
||||
assertEquals("3", format.format(new BigDecimal("2.7")));
|
||||
assertEquals("2", format.format(new BigDecimal("2.5")));
|
||||
assertEquals("4", format.format(new BigDecimal("3.5")));
|
||||
assertEquals("-2", format.format(new BigDecimal("-2.5")));
|
||||
assertEquals("-4", format.format(new BigDecimal("-3.5")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formatsWithGroups() {
|
||||
DecimalFormat format = createFormat("#,###.0");
|
||||
|
@ -228,6 +314,19 @@ public class DecimalFormatTest {
|
|||
assertEquals("000,000,000,000,000,000,023", format.format(23));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formatsBigWithGroups() {
|
||||
DecimalFormat format = createFormat("#,###.0");
|
||||
assertEquals("23.0", format.format(BigInteger.valueOf(23)));
|
||||
assertEquals("2,300.0", format.format(BigInteger.valueOf(2300)));
|
||||
assertEquals("2,300,000,000,000,000,000,000.0", format.format(new BigInteger("2300000000000000000000")));
|
||||
assertEquals("23,000,000,000,000,000,000,000,000.0", format.format(
|
||||
new BigInteger("23000000000000000000000000")));
|
||||
|
||||
format = createFormat("000,000,000,000,000,000,000");
|
||||
assertEquals("000,000,000,000,000,000,023", format.format(BigInteger.valueOf(23)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formatsLargeValues() {
|
||||
DecimalFormat format = createFormat("0");
|
||||
|
@ -264,6 +363,35 @@ public class DecimalFormatTest {
|
|||
assertEquals("1.234E4", format.format(12345));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formatsBigExponent() {
|
||||
DecimalFormat format = createFormat("000E0");
|
||||
assertEquals("230E-1", format.format(BigInteger.valueOf(23)));
|
||||
assertEquals("230E0", format.format(BigInteger.valueOf(230)));
|
||||
assertEquals("230E1", format.format(BigInteger.valueOf(2300)));
|
||||
assertEquals("123E1", format.format(BigInteger.valueOf(1234)));
|
||||
assertEquals("-123E1", format.format(BigInteger.valueOf(-1234)));
|
||||
|
||||
format = createFormat("0.00E0");
|
||||
assertEquals("2.00E1", format.format(BigInteger.valueOf(20)));
|
||||
assertEquals("2.30E1", format.format(BigInteger.valueOf(23)));
|
||||
assertEquals("2.30E2", format.format(BigInteger.valueOf(230)));
|
||||
assertEquals("1.23E3", format.format(BigInteger.valueOf(1234)));
|
||||
|
||||
format = createFormat("000000000000000000000.00E0");
|
||||
assertEquals("230000000000000000000.00E-19", format.format(BigInteger.valueOf(23)));
|
||||
|
||||
format = createFormat("0.0000000000000000000000E0");
|
||||
assertEquals("2.3000000000000000000000E1", format.format(BigInteger.valueOf(23)));
|
||||
|
||||
format = createFormat("0.0##E0");
|
||||
assertEquals("1.0E0", format.format(BigInteger.valueOf(1)));
|
||||
assertEquals("1.2E1", format.format(BigInteger.valueOf(12)));
|
||||
assertEquals("1.23E2", format.format(BigInteger.valueOf(123)));
|
||||
assertEquals("1.234E3", format.format(BigInteger.valueOf(1234)));
|
||||
assertEquals("1.234E4", format.format(BigInteger.valueOf(12345)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formatsExponentWithMultiplier() {
|
||||
DecimalFormat format = createFormat("##0.00E0");
|
||||
|
@ -274,6 +402,44 @@ public class DecimalFormatTest {
|
|||
assertEquals("23.0E3", format.format(23000));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formatsBigExponentWithMultiplier() {
|
||||
DecimalFormat format = createFormat("##0.00E0");
|
||||
assertEquals("2.30E0", format.format(new BigDecimal("2.3")));
|
||||
assertEquals("23.0E0", format.format(new BigDecimal("23")));
|
||||
assertEquals("230E0", format.format(new BigDecimal("230")));
|
||||
assertEquals("2.30E3", format.format(new BigDecimal("2300")));
|
||||
assertEquals("23.0E3", format.format(new BigDecimal("23000")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formatsSpecialValues() {
|
||||
DecimalFormat format = createFormat("0");
|
||||
assertEquals("∞", format.format(Double.POSITIVE_INFINITY));
|
||||
assertEquals("-∞", format.format(Double.NEGATIVE_INFINITY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formatsWithMultiplier() {
|
||||
DecimalFormat format = createFormat("0");
|
||||
format.setMultiplier(2);
|
||||
assertEquals("18446744073709551614", format.format(9223372036854775807L));
|
||||
assertEquals("46", format.format(BigInteger.valueOf(23)));
|
||||
|
||||
format.setMultiplier(100);
|
||||
assertEquals("2300", format.format(23));
|
||||
assertEquals("2300", format.format(BigInteger.valueOf(23)));
|
||||
|
||||
format = createFormat("00E0");
|
||||
format.setMultiplier(2);
|
||||
assertEquals("18E18", format.format(9223372036854775807L));
|
||||
assertEquals("46E0", format.format(BigInteger.valueOf(23)));
|
||||
|
||||
format.setMultiplier(100);
|
||||
assertEquals("23E2", format.format(23));
|
||||
assertEquals("23E2", format.format(BigInteger.valueOf(23)));
|
||||
}
|
||||
|
||||
private DecimalFormat createFormat(String format) {
|
||||
return new DecimalFormat(format, symbols);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user