blob: 76c2e160085a0f38ebeb3ea939ce8b3c6e603bb8 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.text.numbers;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.function.BiFunction;
import org.apache.commons.rng.UniformRandomProvider;
import org.apache.commons.rng.simple.RandomSource;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.function.Executable;
class ParsedDecimalTest {
private static final class FormatOptionsImpl implements ParsedDecimal.FormatOptions {
private boolean includeFractionPlaceholder = true;
private boolean signedZero = true;
private char[] digits = "0123456789".toCharArray();
private char decimalSeparator = '.';
private char thousandsGroupingSeparator = ',';
private boolean groupThousands = false;
private char minusSign = '-';
private String exponentSeparator = "E";
private boolean alwaysIncludeExponent = false;
@Override
public char getDecimalSeparator() {
return decimalSeparator;
}
@Override
public char[] getDigits() {
return digits;
}
@Override
public char[] getExponentSeparatorChars() {
return exponentSeparator.toCharArray();
}
@Override
public char getGroupingSeparator() {
return thousandsGroupingSeparator;
}
@Override
public char getMinusSign() {
return minusSign;
}
@Override
public boolean isAlwaysIncludeExponent() {
return alwaysIncludeExponent;
}
@Override
public boolean isGroupThousands() {
return groupThousands;
}
@Override
public boolean isIncludeFractionPlaceholder() {
return includeFractionPlaceholder;
}
@Override
public boolean isSignedZero() {
return signedZero;
}
public void setAlwaysIncludeExponent(final boolean alwaysIncludeExponent) {
this.alwaysIncludeExponent = alwaysIncludeExponent;
}
public void setDecimalSeparator(final char decimalSeparator) {
this.decimalSeparator = decimalSeparator;
}
public void setDigitsFromString(final String digits) {
this.digits = digits.toCharArray();
}
public void setExponentSeparator(final String exponentSeparator) {
this.exponentSeparator = exponentSeparator;
}
public void setGroupThousands(final boolean groupThousands) {
this.groupThousands = groupThousands;
}
public void setIncludeFractionPlaceholder(final boolean includeFractionPlaceholder) {
this.includeFractionPlaceholder = includeFractionPlaceholder;
}
public void setMinusSign(final char minusSign) {
this.minusSign = minusSign;
}
public void setSignedZero(final boolean signedZero) {
this.signedZero = signedZero;
}
public void setThousandsGroupingSeparator(final char thousandsGroupingSeparator) {
this.thousandsGroupingSeparator = thousandsGroupingSeparator;
}
}
private static void assertMaxPrecision(final double d, final int maxPrecision,
final boolean negative, final String digits, final int exponent) {
final ParsedDecimal dec = ParsedDecimal.from(d);
dec.maxPrecision(maxPrecision);
assertSimpleDecimal(dec, negative, digits, exponent);
}
private static void assertRound(final double d, final int roundExponent,
final boolean negative, final String digits, final int exponent) {
final ParsedDecimal dec = ParsedDecimal.from(d);
dec.round(roundExponent);
assertSimpleDecimal(dec, negative, digits, exponent);
}
private static void assertSimpleDecimal(final ParsedDecimal parsed, final boolean negative, final String digits,
final int exponent) {
Assertions.assertEquals(negative, parsed.negative);
Assertions.assertEquals(digits, digitString(parsed));
Assertions.assertEquals(exponent, parsed.getExponent());
Assertions.assertEquals(digits.length(), parsed.digitCount);
Assertions.assertEquals(exponent, parsed.getScientificExponent() - digits.length() + 1);
}
private static void assertThrowsWithMessage(final Executable fn, final Class<? extends Throwable> type,
final String msg) {
final Throwable exc = Assertions.assertThrows(type, fn);
Assertions.assertEquals(msg, exc.getMessage());
}
private static void checkFrom(final double d, final String digits, final int exponent) {
final boolean negative = Math.signum(d) < 0;
assertSimpleDecimal(ParsedDecimal.from(d), negative, digits, exponent);
assertSimpleDecimal(ParsedDecimal.from(-d), !negative, digits, exponent);
}
private static void checkToEngineeringString(final double d, final String expected,
final ParsedDecimal.FormatOptions opts) {
checkToStringMethod(d, expected, ParsedDecimal::toEngineeringString, opts);
// check the exponent value to make sure it is a multiple of 3
final String pos = ParsedDecimal.from(d).toEngineeringString(opts);
Assertions.assertEquals(0, parseExponent(pos, opts) % 3);
final String neg = ParsedDecimal.from(-d).toEngineeringString(opts);
Assertions.assertEquals(0, parseExponent(neg, opts) % 3);
}
private static void checkToPlainString(final double d, final String expected,
final ParsedDecimal.FormatOptions opts) {
checkToStringMethod(d, expected, ParsedDecimal::toPlainString, opts);
}
private static void checkToScientificString(final double d, final String expected,
final ParsedDecimal.FormatOptions opts) {
checkToStringMethod(d, expected, ParsedDecimal::toScientificString, opts);
}
private static void checkToStringMethod(final double d, final String expected,
final BiFunction<ParsedDecimal, ParsedDecimal.FormatOptions, String> fn,
final ParsedDecimal.FormatOptions opts) {
final ParsedDecimal pos = ParsedDecimal.from(d);
final String actual = fn.apply(pos, opts);
Assertions.assertEquals(expected, actual);
}
private static double createRandomDouble(final UniformRandomProvider rng) {
final long mask = (1L << 52) - 1 | 1L << 63;
final long bits = rng.nextLong() & mask;
final long exp = rng.nextInt(2045) + 1;
return Double.longBitsToDouble(bits | exp << 52);
}
/** Get the raw digits in the given decimal as a string.
* @param dec decimal instancE
* @return decimal digits as a string
*/
private static String digitString(final ParsedDecimal dec) {
final StringBuilder sb = new StringBuilder();
for (int i = 0; i < dec.digitCount; ++i) {
sb.append(dec.digits[i]);
}
return sb.toString();
}
private static int parseExponent(final String str, final ParsedDecimal.FormatOptions opts) {
final char[] expSep = opts.getExponentSeparatorChars();
final int expStartIdx = str.indexOf(String.valueOf(expSep));
if (expStartIdx > -1) {
int expIdx = expStartIdx + expSep.length;
boolean neg = false;
if (str.charAt(expIdx) == opts.getMinusSign()) {
++expIdx;
neg = true;
}
final String expStr = str.substring(expIdx);
final int val = Integer.parseInt(expStr);
return neg
? -val
: val;
}
return 0;
}
@Test
void testFrom() {
// act/assert
checkFrom(0.0, "0", 0);
checkFrom(1.0, "1", 0);
checkFrom(10.0, "1", 1);
checkFrom(100.0, "1", 2);
checkFrom(1000.0, "1", 3);
checkFrom(10000.0, "1", 4);
checkFrom(0.1, "1", -1);
checkFrom(0.01, "1", -2);
checkFrom(0.001, "1", -3);
checkFrom(0.0001, "1", -4);
checkFrom(0.00001, "1", -5);
checkFrom(1.2, "12", -1);
checkFrom(0.00971, "971", -5);
checkFrom(56300, "563", 2);
checkFrom(123.0, "123", 0);
checkFrom(1230.0, "123", 1);
checkFrom(12300.0, "123", 2);
checkFrom(123000.0, "123", 3);
checkFrom(12.3, "123", -1);
checkFrom(1.23, "123", -2);
checkFrom(0.123, "123", -3);
checkFrom(0.0123, "123", -4);
checkFrom(1.987654321e270, "1987654321", 261);
checkFrom(1.987654321e-270, "1987654321", -279);
checkFrom(Math.PI, "3141592653589793", -15);
checkFrom(Math.E, "2718281828459045", -15);
checkFrom(Double.MAX_VALUE, "17976931348623157", 292);
checkFrom(Double.MIN_VALUE, "49", -325);
checkFrom(Double.MIN_NORMAL, "22250738585072014", -324);
}
@Test
void testFrom_notFinite() {
// arrange
final String msg = "Double is not finite";
// act/assert
assertThrowsWithMessage(() -> ParsedDecimal.from(Double.NaN),
IllegalArgumentException.class, msg);
assertThrowsWithMessage(() -> ParsedDecimal.from(Double.NEGATIVE_INFINITY),
IllegalArgumentException.class, msg);
assertThrowsWithMessage(() -> ParsedDecimal.from(Double.POSITIVE_INFINITY),
IllegalArgumentException.class, msg);
}
@Test
void testIsZero() {
// act/assert
Assertions.assertTrue(ParsedDecimal.from(0.0).isZero());
Assertions.assertTrue(ParsedDecimal.from(-0.0).isZero());
Assertions.assertFalse(ParsedDecimal.from(1.0).isZero());
Assertions.assertFalse(ParsedDecimal.from(-1.0).isZero());
Assertions.assertFalse(ParsedDecimal.from(Double.MIN_NORMAL).isZero());
Assertions.assertFalse(ParsedDecimal.from(-Double.MIN_NORMAL).isZero());
Assertions.assertFalse(ParsedDecimal.from(Double.MAX_VALUE).isZero());
Assertions.assertFalse(ParsedDecimal.from(-Double.MIN_VALUE).isZero());
}
@Test
void testMaxPrecision() {
// arrange
final double d = 1.02576552;
// act
assertMaxPrecision(d, 10, false, "102576552", -8);
assertMaxPrecision(d, 9, false, "102576552", -8);
assertMaxPrecision(d, 8, false, "10257655", -7);
assertMaxPrecision(d, 7, false, "1025766", -6);
assertMaxPrecision(d, 6, false, "102577", -5);
assertMaxPrecision(d, 5, false, "10258", -4);
assertMaxPrecision(d, 4, false, "1026", -3);
assertMaxPrecision(d, 3, false, "103", -2);
assertMaxPrecision(d, 2, false, "1", 0);
assertMaxPrecision(d, 1, false, "1", 0);
assertMaxPrecision(d, 0, false, "102576552", -8);
}
@Test
void testMaxPrecision_carry() {
// arrange
final double d = -999.0999e50;
// act
assertMaxPrecision(d, 8, true, "9990999", 46);
assertMaxPrecision(d, 7, true, "9990999", 46);
assertMaxPrecision(d, 6, true, "9991", 49);
assertMaxPrecision(d, 5, true, "9991", 49);
assertMaxPrecision(d, 4, true, "9991", 49);
assertMaxPrecision(d, 3, true, "999", 50);
assertMaxPrecision(d, 2, true, "1", 53);
assertMaxPrecision(d, 1, true, "1", 53);
assertMaxPrecision(d, 0, true, "9990999", 46);
}
@Test
void testMaxPrecision_halfEvenRounding() {
// act/assert
// Test values taken from RoundingMode.HALF_EVEN javadocs
assertMaxPrecision(5.5, 1, false, "6", 0);
assertMaxPrecision(2.5, 1, false, "2", 0);
assertMaxPrecision(1.6, 1, false, "2", 0);
assertMaxPrecision(1.1, 1, false, "1", 0);
assertMaxPrecision(1.0, 1, false, "1", 0);
assertMaxPrecision(-1.0, 1, true, "1", 0);
assertMaxPrecision(-1.1, 1, true, "1", 0);
assertMaxPrecision(-1.6, 1, true, "2", 0);
assertMaxPrecision(-2.5, 1, true, "2", 0);
assertMaxPrecision(-5.5, 1, true, "6", 0);
}
@Test
void testMaxPrecision_random() {
// arrange
final UniformRandomProvider rand = RandomSource.create(RandomSource.XO_RO_SHI_RO_128_PP, 0L);
final ParsedDecimal.FormatOptions opts = new FormatOptionsImpl();
for (int i = 0; i < 10_000; ++i) {
final double d = createRandomDouble(rand);
final int precision = rand.nextInt(20) + 1;
final MathContext ctx = new MathContext(precision, RoundingMode.HALF_EVEN);
final ParsedDecimal dec = ParsedDecimal.from(d);
// act
dec.maxPrecision(precision);
// assert
Assertions.assertEquals(new BigDecimal(Double.toString(d), ctx).doubleValue(),
Double.parseDouble(dec.toScientificString(opts)));
}
}
@Test
void testMaxPrecision_singleDigits() {
// act
assertMaxPrecision(9.0, 1, false, "9", 0);
assertMaxPrecision(1.0, 1, false, "1", 0);
assertMaxPrecision(0.0, 1, false, "0", 0);
assertMaxPrecision(-0.0, 1, true, "0", 0);
assertMaxPrecision(-1.0, 1, true, "1", 0);
assertMaxPrecision(-9.0, 1, true, "9", 0);
}
@Test
void testRound_mixed() {
// arrange
final double a = 9.94e-10;
final double b = -3.1415;
final double c = 5.55e10;
// act/assert
assertRound(a, -13, false, "994", -12);
assertRound(a, -12, false, "994", -12);
assertRound(a, -11, false, "99", -11);
assertRound(a, -10, false, "1", -9);
assertRound(a, -9, false, "1", -9);
assertRound(a, -8, false, "0", 0);
assertRound(b, -5, true, "31415", -4);
assertRound(b, -4, true, "31415", -4);
assertRound(b, -3, true, "3142", -3);
assertRound(b, -2, true, "314", -2);
assertRound(b, -1, true, "31", -1);
assertRound(b, 0, true, "3", 0);
assertRound(b, 1, true, "0", 0);
assertRound(b, 2, true, "0", 0);
assertRound(c, 7, false, "555", 8);
assertRound(c, 8, false, "555", 8);
assertRound(c, 9, false, "56", 9);
assertRound(c, 10, false, "6", 10);
assertRound(c, 11, false, "1", 11);
assertRound(c, 12, false, "0", 0);
}
@Test
void testRound_nine() {
// arrange
final double a = 9e-10;
final double b = -9;
final double c = 9e10;
// act/assert
assertRound(a, -11, false, "9", -10);
assertRound(a, -10, false, "9", -10);
assertRound(a, -9, false, "1", -9);
assertRound(b, -1, true, "9", 0);
assertRound(b, 0, true, "9", 0);
assertRound(b, 1, true, "1", 1);
assertRound(c, 9, false, "9", 10);
assertRound(c, 10, false, "9", 10);
assertRound(c, 11, false, "1", 11);
}
@Test
void testRound_one() {
// arrange
final double a = 1e-10;
final double b = -1;
final double c = 1e10;
// act/assert
assertRound(a, -11, false, "1", -10);
assertRound(a, -10, false, "1", -10);
assertRound(a, -9, false, "0", 0);
assertRound(b, -1, true, "1", 0);
assertRound(b, 0, true, "1", 0);
assertRound(b, 1, true, "0", 0);
assertRound(c, 9, false, "1", 10);
assertRound(c, 10, false, "1", 10);
assertRound(c, 11, false, "0", 0);
}
@Test
void testStringMethodAccuracy_random() {
// arrange
final UniformRandomProvider rand = RandomSource.create(RandomSource.XO_RO_SHI_RO_128_PP, 0L);
final FormatOptionsImpl stdOpts = new FormatOptionsImpl();
final FormatOptionsImpl altOpts = new FormatOptionsImpl();
altOpts.setExponentSeparator("e");
altOpts.setIncludeFractionPlaceholder(false);
double d;
for (int i = 0; i < 10_000; ++i) {
d = createRandomDouble(rand);
// act/assert
Assertions.assertEquals(d, Double.parseDouble(ParsedDecimal.from(d).toScientificString(stdOpts)));
Assertions.assertEquals(d, Double.parseDouble(ParsedDecimal.from(d).toScientificString(altOpts)));
Assertions.assertEquals(d, Double.parseDouble(ParsedDecimal.from(d).toEngineeringString(stdOpts)));
Assertions.assertEquals(d, Double.parseDouble(ParsedDecimal.from(d).toEngineeringString(altOpts)));
Assertions.assertEquals(d, Double.parseDouble(ParsedDecimal.from(d).toPlainString(stdOpts)));
Assertions.assertEquals(d, Double.parseDouble(ParsedDecimal.from(d).toPlainString(altOpts)));
}
}
@Test
void testStringMethodAccuracy_sequence() {
// arrange
final double min = -1000;
final double max = 1000;
final double delta = 0.1;
final FormatOptionsImpl stdOpts = new FormatOptionsImpl();
final FormatOptionsImpl altOpts = new FormatOptionsImpl();
altOpts.setExponentSeparator("e");
altOpts.setIncludeFractionPlaceholder(false);
Assertions.assertEquals(10.0, Double.parseDouble(ParsedDecimal.from(10.0).toScientificString(stdOpts)));
for (double d = min; d <= max; d += delta) {
// act/assert
Assertions.assertEquals(d, Double.parseDouble(ParsedDecimal.from(d).toScientificString(stdOpts)));
Assertions.assertEquals(d, Double.parseDouble(ParsedDecimal.from(d).toScientificString(altOpts)));
Assertions.assertEquals(d, Double.parseDouble(ParsedDecimal.from(d).toEngineeringString(stdOpts)));
Assertions.assertEquals(d, Double.parseDouble(ParsedDecimal.from(d).toEngineeringString(altOpts)));
Assertions.assertEquals(d, Double.parseDouble(ParsedDecimal.from(d).toPlainString(stdOpts)));
Assertions.assertEquals(d, Double.parseDouble(ParsedDecimal.from(d).toPlainString(altOpts)));
}
}
@Test
void testStringMethods_customDigits() {
// arrange
final FormatOptionsImpl opts = new FormatOptionsImpl();
opts.setDigitsFromString("abcdefghij");
// act/assert
Assertions.assertEquals("b.a", ParsedDecimal.from(1.0).toPlainString(opts));
Assertions.assertEquals("-a.abcd", ParsedDecimal.from(-0.0123).toPlainString(opts));
Assertions.assertEquals("bc.de", ParsedDecimal.from(12.34).toPlainString(opts));
Assertions.assertEquals("baaaa.a", ParsedDecimal.from(10000).toPlainString(opts));
Assertions.assertEquals("jihgfedcba.a", ParsedDecimal.from(9876543210d).toPlainString(opts));
Assertions.assertEquals("b.a", ParsedDecimal.from(1.0).toScientificString(opts));
Assertions.assertEquals("-b.cdE-c", ParsedDecimal.from(-0.0123).toScientificString(opts));
Assertions.assertEquals("b.cdeEb", ParsedDecimal.from(12.34).toScientificString(opts));
Assertions.assertEquals("b.aEe", ParsedDecimal.from(10000).toScientificString(opts));
Assertions.assertEquals("j.ihgfedcbEj", ParsedDecimal.from(9876543210d).toScientificString(opts));
Assertions.assertEquals("b.a", ParsedDecimal.from(1.0).toEngineeringString(opts));
Assertions.assertEquals("-bc.dE-d", ParsedDecimal.from(-0.0123).toEngineeringString(opts));
Assertions.assertEquals("bc.de", ParsedDecimal.from(12.34).toEngineeringString(opts));
Assertions.assertEquals("ba.aEd", ParsedDecimal.from(10000).toEngineeringString(opts));
Assertions.assertEquals("j.ihgfedcbEj", ParsedDecimal.from(9876543210d).toEngineeringString(opts));
}
@Test
void testToEngineeringString_altFormat() {
// arrange
final FormatOptionsImpl opts = new FormatOptionsImpl();
opts.setIncludeFractionPlaceholder(false);
opts.setSignedZero(false);
opts.setDecimalSeparator(',');
opts.setMinusSign('!');
opts.setExponentSeparator("x10^");
opts.setAlwaysIncludeExponent(true);
// act/assert
checkToEngineeringString(0.0, "0x10^0", opts);
checkToEngineeringString(-0.0, "0x10^0", opts);
checkToEngineeringString(1.0, "1x10^0", opts);
checkToEngineeringString(1.5, "1,5x10^0", opts);
checkToEngineeringString(10, "10x10^0", opts);
checkToEngineeringString(-0.000000123, "!123x10^!9", opts);
checkToEngineeringString(12300000, "12,3x10^6", opts);
checkToEngineeringString(Math.PI, "3,141592653589793x10^0", opts);
checkToEngineeringString(Math.E, "2,718281828459045x10^0", opts);
checkToEngineeringString(-Double.MAX_VALUE, "!179,76931348623157x10^306", opts);
checkToEngineeringString(Double.MIN_VALUE, "4,9x10^!324", opts);
checkToEngineeringString(Double.MIN_NORMAL, "22,250738585072014x10^!309", opts);
}
@Test
void testToEngineeringString_defaults() {
// arrange
final FormatOptionsImpl opts = new FormatOptionsImpl();
// act/assert
checkToEngineeringString(0.0, "0.0", opts);
checkToEngineeringString(-0.0, "-0.0", opts);
checkToEngineeringString(1.0, "1.0", opts);
checkToEngineeringString(1.5, "1.5", opts);
checkToEngineeringString(10, "10.0", opts);
checkToEngineeringString(-0.000000123, "-123.0E-9", opts);
checkToEngineeringString(12300000, "12.3E6", opts);
checkToEngineeringString(Math.PI, "3.141592653589793", opts);
checkToEngineeringString(Math.E, "2.718281828459045", opts);
checkToEngineeringString(-Double.MAX_VALUE, "-179.76931348623157E306", opts);
checkToEngineeringString(Double.MIN_VALUE, "4.9E-324", opts);
checkToEngineeringString(Double.MIN_NORMAL, "22.250738585072014E-309", opts);
}
@Test
void testToPlainString_altFormat() {
// arrange
final FormatOptionsImpl opts = new FormatOptionsImpl();
opts.setIncludeFractionPlaceholder(false);
opts.setSignedZero(false);
opts.setDecimalSeparator(',');
opts.setMinusSign('!');
opts.setThousandsGroupingSeparator('_');
opts.setGroupThousands(true);
// act/assert
checkToPlainString(0.0, "0", opts);
checkToPlainString(-0.0, "0", opts);
checkToPlainString(1.0, "1", opts);
checkToPlainString(1.5, "1,5", opts);
checkToPlainString(12, "12", opts);
checkToPlainString(123, "123", opts);
checkToPlainString(1234, "1_234", opts);
checkToPlainString(12345, "12_345", opts);
checkToPlainString(123456, "123_456", opts);
checkToPlainString(1234567, "1_234_567", opts);
checkToPlainString(12345678, "12_345_678", opts);
checkToPlainString(123456789, "123_456_789", opts);
checkToPlainString(1234567890, "1_234_567_890", opts);
checkToPlainString(-0.000123, "!0,000123", opts);
checkToPlainString(12301, "12_301", opts);
checkToPlainString(Math.PI, "3,141592653589793", opts);
checkToPlainString(Math.E, "2,718281828459045", opts);
checkToPlainString(-12345.6789, "!12_345,6789", opts);
checkToPlainString(1.23e12, "1_230_000_000_000", opts);
checkToPlainString(1.23e-12, "0,00000000000123", opts);
}
@Test
void testToPlainString_defaults() {
// arrange
final FormatOptionsImpl opts = new FormatOptionsImpl();
// act/assert
checkToPlainString(0.0, "0.0", opts);
checkToPlainString(-0.0, "-0.0", opts);
checkToPlainString(1.0, "1.0", opts);
checkToPlainString(1.5, "1.5", opts);
checkToPlainString(12, "12.0", opts);
checkToPlainString(123, "123.0", opts);
checkToPlainString(1234, "1234.0", opts);
checkToPlainString(12345, "12345.0", opts);
checkToPlainString(123456, "123456.0", opts);
checkToPlainString(1234567, "1234567.0", opts);
checkToPlainString(12345678, "12345678.0", opts);
checkToPlainString(123456789, "123456789.0", opts);
checkToPlainString(1234567890, "1234567890.0", opts);
checkToPlainString(-0.000123, "-0.000123", opts);
checkToPlainString(12301, "12301.0", opts);
checkToPlainString(Math.PI, "3.141592653589793", opts);
checkToPlainString(Math.E, "2.718281828459045", opts);
checkToPlainString(-12345.6789, "-12345.6789", opts);
checkToPlainString(1.23e12, "1230000000000.0", opts);
checkToPlainString(1.23e-12, "0.00000000000123", opts);
}
@Test
void testToScientificString_altFormats() {
// arrange
final FormatOptionsImpl opts = new FormatOptionsImpl();
opts.setIncludeFractionPlaceholder(false);
opts.setSignedZero(false);
opts.setDecimalSeparator(',');
opts.setMinusSign('!');
opts.setExponentSeparator("x10^");
opts.setAlwaysIncludeExponent(true);
// act/assert
checkToScientificString(0.0, "0x10^0", opts);
checkToScientificString(-0.0, "0x10^0", opts);
checkToScientificString(1.0, "1x10^0", opts);
checkToScientificString(1.5, "1,5x10^0", opts);
checkToScientificString(-0.000123, "!1,23x10^!4", opts);
checkToScientificString(12301, "1,2301x10^4", opts);
checkToScientificString(Math.PI, "3,141592653589793x10^0", opts);
checkToScientificString(Math.E, "2,718281828459045x10^0", opts);
checkToScientificString(-Double.MAX_VALUE, "!1,7976931348623157x10^308", opts);
checkToScientificString(Double.MIN_VALUE, "4,9x10^!324", opts);
checkToScientificString(Double.MIN_NORMAL, "2,2250738585072014x10^!308", opts);
}
@Test
void testToScientificString_defaults() {
// arrange
final FormatOptionsImpl opts = new FormatOptionsImpl();
// act/assert
checkToScientificString(0.0, "0.0", opts);
checkToScientificString(-0.0, "-0.0", opts);
checkToScientificString(1.0, "1.0", opts);
checkToScientificString(1.5, "1.5", opts);
checkToScientificString(-0.000123, "-1.23E-4", opts);
checkToScientificString(12301, "1.2301E4", opts);
checkToScientificString(Math.PI, "3.141592653589793", opts);
checkToScientificString(Math.E, "2.718281828459045", opts);
checkToScientificString(-Double.MAX_VALUE, "-1.7976931348623157E308", opts);
checkToScientificString(Double.MIN_VALUE, "4.9E-324", opts);
checkToScientificString(Double.MIN_NORMAL, "2.2250738585072014E-308", opts);
}
}