8159023: Engineering notation of DecimalFormat does not work as documented
Reviewed-by: naoto
This commit is contained in:
parent
ee321c70e5
commit
46c4da7fdd
@ -264,6 +264,16 @@ import sun.util.locale.provider.ResourceBundleBasedAdapter;
|
|||||||
* formatted using the localized minus sign, <em>not</em> the prefix and suffix
|
* formatted using the localized minus sign, <em>not</em> the prefix and suffix
|
||||||
* from the pattern. This allows patterns such as {@code "0.###E0 m/s"}.
|
* from the pattern. This allows patterns such as {@code "0.###E0 m/s"}.
|
||||||
*
|
*
|
||||||
|
* <li>The <em>maximum integer</em> digits is the sum of '0's and '#'s
|
||||||
|
* prior to the decimal point. The <em>minimum integer</em> digits is the
|
||||||
|
* sum of the '0's prior to the decimal point. The <em>maximum fraction</em>
|
||||||
|
* and <em>minimum fraction</em> digits follow the same rules, but apply to the
|
||||||
|
* digits after the decimal point but before the exponent. For example, the
|
||||||
|
* following pattern: {@code "#00.0####E0"} would have a minimum number of
|
||||||
|
* integer digits = 2("00") and a maximum number of integer digits = 3("#00"). It
|
||||||
|
* would have a minimum number of fraction digits = 1("0") and a maximum number of fraction
|
||||||
|
* digits= 5("0####").
|
||||||
|
*
|
||||||
* <li>The minimum and maximum number of integer digits are interpreted
|
* <li>The minimum and maximum number of integer digits are interpreted
|
||||||
* together:
|
* together:
|
||||||
*
|
*
|
||||||
@ -282,13 +292,38 @@ import sun.util.locale.provider.ResourceBundleBasedAdapter;
|
|||||||
* {@code "12.3E-4"}.
|
* {@code "12.3E-4"}.
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* <li>The number of significant digits in the mantissa is the sum of the
|
* <li>For a given number, the amount of significant digits in
|
||||||
* <em>minimum integer</em> and <em>maximum fraction</em> digits, and is
|
* the mantissa can be calculated as such
|
||||||
* unaffected by the maximum integer digits. For example, 12345 formatted with
|
*
|
||||||
* {@code "##0.##E0"} is {@code "12.3E3"}. To show all digits, set
|
* <blockquote><pre>
|
||||||
* the significant digits count to zero. The number of significant digits
|
* <i>Mantissa Digits:</i>
|
||||||
|
* min(max(Minimum Pattern Digits, Original Number Digits), Maximum Pattern Digits)
|
||||||
|
* <i>Minimum pattern Digits:</i>
|
||||||
|
* <i>Minimum Integer Digits</i> + <i>Minimum Fraction Digits</i>
|
||||||
|
* <i>Maximum pattern Digits:</i>
|
||||||
|
* <i>Maximum Integer Digits</i> + <i>Maximum Fraction Digits</i>
|
||||||
|
* <i>Original Number Digits:</i>
|
||||||
|
* The amount of significant digits in the number to be formatted
|
||||||
|
* </pre></blockquote>
|
||||||
|
*
|
||||||
|
* This means that generally, a mantissa will have up to the combined maximum integer
|
||||||
|
* and fraction digits, if the original number itself has enough significant digits. However,
|
||||||
|
* if there are more minimum pattern digits than significant digits in the original number,
|
||||||
|
* the mantissa will have significant digits that equals the combined
|
||||||
|
* minimum integer and fraction digits. The number of significant digits
|
||||||
* does not affect parsing.
|
* does not affect parsing.
|
||||||
*
|
*
|
||||||
|
* <p>It should be noted, that the integer portion of the mantissa will give
|
||||||
|
* any excess digits to the fraction portion, whether it be for precision or
|
||||||
|
* for satisfying the total amount of combined minimum digits.
|
||||||
|
*
|
||||||
|
* <p>This behavior can be observed in the following example,
|
||||||
|
* {@snippet lang=java :
|
||||||
|
* DecimalFormat df = new DecimalFormat("#000.000##E0");
|
||||||
|
* df.format(12); // returns "12.0000E0"
|
||||||
|
* df.format(123456789) // returns "1.23456789E8"
|
||||||
|
* }
|
||||||
|
*
|
||||||
* <li>Exponential patterns may not contain grouping separators.
|
* <li>Exponential patterns may not contain grouping separators.
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
@ -308,8 +343,8 @@ import sun.util.locale.provider.ResourceBundleBasedAdapter;
|
|||||||
*
|
*
|
||||||
* <h4>Special Values</h4>
|
* <h4>Special Values</h4>
|
||||||
*
|
*
|
||||||
* <p>{@code NaN} is formatted as a string, which typically has a single character
|
* <p>Not a Number({@code NaN}) is formatted as a string, which typically has a
|
||||||
* {@code U+FFFD}. This string is determined by the
|
* single character {@code U+FFFD}. This string is determined by the
|
||||||
* {@code DecimalFormatSymbols} object. This is the only value for which
|
* {@code DecimalFormatSymbols} object. This is the only value for which
|
||||||
* the prefixes and suffixes are not used.
|
* the prefixes and suffixes are not used.
|
||||||
*
|
*
|
||||||
|
105
test/jdk/java/text/Format/DecimalFormat/MantissaDigits.java
Normal file
105
test/jdk/java/text/Format/DecimalFormat/MantissaDigits.java
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 8159023
|
||||||
|
* @summary Confirm behavior of mantissa for scientific notation in Decimal Format
|
||||||
|
* @run junit MantissaDigits
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import java.text.DecimalFormatSymbols;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.Arguments;
|
||||||
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
public class MantissaDigits {
|
||||||
|
private static final double[] NUMBERS = {
|
||||||
|
1.1, 12.1, 123.1, 1234.1, 12345.1, 123456.1,
|
||||||
|
-1.1, -12.1, -123.1, -1234.1, -12345.1, -123456.1,
|
||||||
|
1, 12, 123, 1234, 12345, 123456, 1234567,
|
||||||
|
-1, -12, -123, -1234, -12345, -123456, -1234567,
|
||||||
|
1.1234, 1.1111, 1.412, 222.333, -771.2222
|
||||||
|
};
|
||||||
|
private static final DecimalFormatSymbols DFS = new DecimalFormatSymbols(Locale.US);
|
||||||
|
private static final String ERRMSG = "%s formatted with %s gives %s, and " +
|
||||||
|
"significant digit count was %s, but the formula provided %s%n";
|
||||||
|
// Hard coded as 1, since all test patterns only have 1 exponent digit
|
||||||
|
private static final int EXPONENTDIGITS = 1;
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("patterns")
|
||||||
|
public void testMantissaDefinition(String pattern, int minDigits, int maxDigits) {
|
||||||
|
DecimalFormat df = new DecimalFormat(pattern, DFS);
|
||||||
|
for (double number : NUMBERS) {
|
||||||
|
// Count the significant digits in the pre-formatted number
|
||||||
|
int originalNumDigits = (int) String.valueOf(number).chars()
|
||||||
|
.filter(Character::isDigit).count();
|
||||||
|
|
||||||
|
if (wholeNumber(number)) {
|
||||||
|
// Trailing 0 should not be counted
|
||||||
|
originalNumDigits--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format the number, then grab the significant
|
||||||
|
// digits inside the mantissa
|
||||||
|
String formattedNum = df.format(number);
|
||||||
|
int mantissaDigits = (int) formattedNum.chars()
|
||||||
|
.filter(Character::isDigit).count() - EXPONENTDIGITS;
|
||||||
|
|
||||||
|
// Test the new definition of the Mantissa
|
||||||
|
Integer calculatedDigits = Math
|
||||||
|
.min(Math.max(minDigits, originalNumDigits), maxDigits);
|
||||||
|
assertEquals(mantissaDigits, calculatedDigits, String.format(ERRMSG,
|
||||||
|
number, pattern, formattedNum, mantissaDigits, calculatedDigits));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Boolean wholeNumber(double number) {
|
||||||
|
return (int) number == number;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Stream<Arguments> patterns() {
|
||||||
|
return Stream.of(
|
||||||
|
Arguments.of("#0.0##E0", 2, 5),
|
||||||
|
Arguments.of("#00.00##E0", 4, 7),
|
||||||
|
Arguments.of("#0.000##E0", 4, 7),
|
||||||
|
Arguments.of("#00.000##E0", 5, 8),
|
||||||
|
Arguments.of("#000.0##E0", 4, 7),
|
||||||
|
Arguments.of("#000.00##E0", 5, 8),
|
||||||
|
Arguments.of("#000.000##E0", 6, 9),
|
||||||
|
Arguments.of("000.000E0", 6, 6),
|
||||||
|
Arguments.of("#.##E0", 0, 3),
|
||||||
|
Arguments.of("######.######E0", 0, 12),
|
||||||
|
Arguments.of("####00.00######E0", 4, 14)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user