1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.text.numbers;
18
19 import java.math.BigDecimal;
20 import java.math.MathContext;
21 import java.math.RoundingMode;
22 import java.util.function.BiFunction;
23
24 import org.apache.commons.rng.UniformRandomProvider;
25 import org.apache.commons.rng.simple.RandomSource;
26 import org.junit.jupiter.api.Assertions;
27 import org.junit.jupiter.api.Test;
28 import org.junit.jupiter.api.function.Executable;
29
30 class ParsedDecimalTest {
31
32 private static final class FormatOptionsImpl implements ParsedDecimal.FormatOptions {
33
34 private boolean includeFractionPlaceholder = true;
35
36 private boolean signedZero = true;
37
38 private char[] digits = "0123456789".toCharArray();
39
40 private char decimalSeparator = '.';
41
42 private char thousandsGroupingSeparator = ',';
43
44 private boolean groupThousands;
45
46 private char minusSign = '-';
47
48 private String exponentSeparator = "E";
49
50 private boolean alwaysIncludeExponent;
51
52 @Override
53 public char getDecimalSeparator() {
54 return decimalSeparator;
55 }
56
57 @Override
58 public char[] getDigits() {
59 return digits;
60 }
61
62 @Override
63 public char[] getExponentSeparatorChars() {
64 return exponentSeparator.toCharArray();
65 }
66
67 @Override
68 public char getGroupingSeparator() {
69 return thousandsGroupingSeparator;
70 }
71
72 @Override
73 public char getMinusSign() {
74 return minusSign;
75 }
76
77 @Override
78 public boolean isAlwaysIncludeExponent() {
79 return alwaysIncludeExponent;
80 }
81
82 @Override
83 public boolean isGroupThousands() {
84 return groupThousands;
85 }
86
87 @Override
88 public boolean isIncludeFractionPlaceholder() {
89 return includeFractionPlaceholder;
90 }
91
92 @Override
93 public boolean isSignedZero() {
94 return signedZero;
95 }
96
97 public void setAlwaysIncludeExponent(final boolean alwaysIncludeExponent) {
98 this.alwaysIncludeExponent = alwaysIncludeExponent;
99 }
100
101 public void setDecimalSeparator(final char decimalSeparator) {
102 this.decimalSeparator = decimalSeparator;
103 }
104
105 public void setDigitsFromString(final String digits) {
106 this.digits = digits.toCharArray();
107 }
108
109 public void setExponentSeparator(final String exponentSeparator) {
110 this.exponentSeparator = exponentSeparator;
111 }
112
113 public void setGroupThousands(final boolean groupThousands) {
114 this.groupThousands = groupThousands;
115 }
116
117 public void setIncludeFractionPlaceholder(final boolean includeFractionPlaceholder) {
118 this.includeFractionPlaceholder = includeFractionPlaceholder;
119 }
120
121 public void setMinusSign(final char minusSign) {
122 this.minusSign = minusSign;
123 }
124
125 public void setSignedZero(final boolean signedZero) {
126 this.signedZero = signedZero;
127 }
128
129 public void setThousandsGroupingSeparator(final char thousandsGroupingSeparator) {
130 this.thousandsGroupingSeparator = thousandsGroupingSeparator;
131 }
132 }
133
134 private static void assertMaxPrecision(final double d, final int maxPrecision,
135 final boolean negative, final String digits, final int exponent) {
136 final ParsedDecimal dec = ParsedDecimal.from(d);
137 dec.maxPrecision(maxPrecision);
138
139 assertSimpleDecimal(dec, negative, digits, exponent);
140 }
141
142 private static void assertRound(final double d, final int roundExponent,
143 final boolean negative, final String digits, final int exponent) {
144 final ParsedDecimal dec = ParsedDecimal.from(d);
145 dec.round(roundExponent);
146
147 assertSimpleDecimal(dec, negative, digits, exponent);
148 }
149
150 private static void assertSimpleDecimal(final ParsedDecimal parsed, final boolean negative, final String digits,
151 final int exponent) {
152 Assertions.assertEquals(negative, parsed.negative);
153 Assertions.assertEquals(digits, digitString(parsed));
154 Assertions.assertEquals(exponent, parsed.getExponent());
155 Assertions.assertEquals(digits.length(), parsed.digitCount);
156 Assertions.assertEquals(exponent, parsed.getScientificExponent() - digits.length() + 1);
157 }
158
159 private static void assertThrowsWithMessage(final Executable fn, final Class<? extends Throwable> type,
160 final String msg) {
161 final Throwable exc = Assertions.assertThrows(type, fn);
162 Assertions.assertEquals(msg, exc.getMessage());
163 }
164
165 private static void checkFrom(final double d, final String digits, final int exponent) {
166 final boolean negative = Math.signum(d) < 0;
167
168 assertSimpleDecimal(ParsedDecimal.from(d), negative, digits, exponent);
169 assertSimpleDecimal(ParsedDecimal.from(-d), !negative, digits, exponent);
170 }
171
172 private static void checkToEngineeringString(final double d, final String expected,
173 final ParsedDecimal.FormatOptions opts) {
174 checkToStringMethod(d, expected, ParsedDecimal::toEngineeringString, opts);
175
176
177 final String pos = ParsedDecimal.from(d).toEngineeringString(opts);
178 Assertions.assertEquals(0, parseExponent(pos, opts) % 3);
179
180 final String neg = ParsedDecimal.from(-d).toEngineeringString(opts);
181 Assertions.assertEquals(0, parseExponent(neg, opts) % 3);
182 }
183
184 private static void checkToPlainString(final double d, final String expected,
185 final ParsedDecimal.FormatOptions opts) {
186 checkToStringMethod(d, expected, ParsedDecimal::toPlainString, opts);
187 }
188
189 private static void checkToScientificString(final double d, final String expected,
190 final ParsedDecimal.FormatOptions opts) {
191 checkToStringMethod(d, expected, ParsedDecimal::toScientificString, opts);
192 }
193
194 private static void checkToStringMethod(final double d, final String expected,
195 final BiFunction<ParsedDecimal, ParsedDecimal.FormatOptions, String> fn,
196 final ParsedDecimal.FormatOptions opts) {
197
198 final ParsedDecimal pos = ParsedDecimal.from(d);
199 final String actual = fn.apply(pos, opts);
200
201 Assertions.assertEquals(expected, actual);
202 }
203
204 private static double createRandomDouble(final UniformRandomProvider rng) {
205 final long mask = (1L << 52) - 1 | 1L << 63;
206 final long bits = rng.nextLong() & mask;
207 final long exp = rng.nextInt(2045) + 1;
208 return Double.longBitsToDouble(bits | exp << 52);
209 }
210
211
212
213
214
215 private static String digitString(final ParsedDecimal dec) {
216 final StringBuilder sb = new StringBuilder();
217 for (int i = 0; i < dec.digitCount; ++i) {
218 sb.append(dec.digits[i]);
219 }
220 return sb.toString();
221 }
222
223 private static int parseExponent(final String str, final ParsedDecimal.FormatOptions opts) {
224 final char[] expSep = opts.getExponentSeparatorChars();
225
226 final int expStartIdx = str.indexOf(String.valueOf(expSep));
227 if (expStartIdx > -1) {
228 int expIdx = expStartIdx + expSep.length;
229
230 boolean neg = false;
231 if (str.charAt(expIdx) == opts.getMinusSign()) {
232 ++expIdx;
233 neg = true;
234 }
235
236 final String expStr = str.substring(expIdx);
237 final int val = Integer.parseInt(expStr);
238 return neg
239 ? -val
240 : val;
241 }
242
243 return 0;
244 }
245
246 @Test
247 void testFrom() {
248
249 checkFrom(0.0, "0", 0);
250
251 checkFrom(1.0, "1", 0);
252 checkFrom(10.0, "1", 1);
253 checkFrom(100.0, "1", 2);
254 checkFrom(1000.0, "1", 3);
255 checkFrom(10000.0, "1", 4);
256
257 checkFrom(0.1, "1", -1);
258 checkFrom(0.01, "1", -2);
259 checkFrom(0.001, "1", -3);
260 checkFrom(0.0001, "1", -4);
261 checkFrom(0.00001, "1", -5);
262
263 checkFrom(1.2, "12", -1);
264 checkFrom(0.00971, "971", -5);
265 checkFrom(56300, "563", 2);
266
267 checkFrom(123.0, "123", 0);
268 checkFrom(1230.0, "123", 1);
269 checkFrom(12300.0, "123", 2);
270 checkFrom(123000.0, "123", 3);
271
272 checkFrom(12.3, "123", -1);
273 checkFrom(1.23, "123", -2);
274 checkFrom(0.123, "123", -3);
275 checkFrom(0.0123, "123", -4);
276
277 checkFrom(1.987654321e270, "1987654321", 261);
278 checkFrom(1.987654321e-270, "1987654321", -279);
279
280 checkFrom(Math.PI, "3141592653589793", -15);
281 checkFrom(Math.E, "2718281828459045", -15);
282
283 checkFrom(Double.MAX_VALUE, "17976931348623157", 292);
284 checkFrom(Double.MIN_VALUE, "49", -325);
285 checkFrom(Double.MIN_NORMAL, "22250738585072014", -324);
286 }
287
288 @Test
289 void testFromNotFinite() {
290
291 final String msg = "Double is not finite";
292
293
294 assertThrowsWithMessage(() -> ParsedDecimal.from(Double.NaN),
295 IllegalArgumentException.class, msg);
296 assertThrowsWithMessage(() -> ParsedDecimal.from(Double.NEGATIVE_INFINITY),
297 IllegalArgumentException.class, msg);
298 assertThrowsWithMessage(() -> ParsedDecimal.from(Double.POSITIVE_INFINITY),
299 IllegalArgumentException.class, msg);
300 }
301
302 @Test
303 void testIsZero() {
304
305 Assertions.assertTrue(ParsedDecimal.from(0.0).isZero());
306 Assertions.assertTrue(ParsedDecimal.from(-0.0).isZero());
307
308 Assertions.assertFalse(ParsedDecimal.from(1.0).isZero());
309 Assertions.assertFalse(ParsedDecimal.from(-1.0).isZero());
310
311 Assertions.assertFalse(ParsedDecimal.from(Double.MIN_NORMAL).isZero());
312 Assertions.assertFalse(ParsedDecimal.from(-Double.MIN_NORMAL).isZero());
313
314 Assertions.assertFalse(ParsedDecimal.from(Double.MAX_VALUE).isZero());
315 Assertions.assertFalse(ParsedDecimal.from(-Double.MIN_VALUE).isZero());
316 }
317
318 @Test
319 void testMaxPrecision() {
320
321 final double d = 1.02576552;
322
323
324 assertMaxPrecision(d, 10, false, "102576552", -8);
325 assertMaxPrecision(d, 9, false, "102576552", -8);
326 assertMaxPrecision(d, 8, false, "10257655", -7);
327 assertMaxPrecision(d, 7, false, "1025766", -6);
328 assertMaxPrecision(d, 6, false, "102577", -5);
329 assertMaxPrecision(d, 5, false, "10258", -4);
330 assertMaxPrecision(d, 4, false, "1026", -3);
331 assertMaxPrecision(d, 3, false, "103", -2);
332 assertMaxPrecision(d, 2, false, "1", 0);
333 assertMaxPrecision(d, 1, false, "1", 0);
334
335 assertMaxPrecision(d, 0, false, "102576552", -8);
336 }
337
338 @Test
339 void testMaxPrecision_carry() {
340
341 final double d = -999.0999e50;
342
343
344 assertMaxPrecision(d, 8, true, "9990999", 46);
345 assertMaxPrecision(d, 7, true, "9990999", 46);
346 assertMaxPrecision(d, 6, true, "9991", 49);
347 assertMaxPrecision(d, 5, true, "9991", 49);
348 assertMaxPrecision(d, 4, true, "9991", 49);
349 assertMaxPrecision(d, 3, true, "999", 50);
350 assertMaxPrecision(d, 2, true, "1", 53);
351 assertMaxPrecision(d, 1, true, "1", 53);
352
353 assertMaxPrecision(d, 0, true, "9990999", 46);
354 }
355
356 @Test
357 void testMaxPrecision_halfEvenRounding() {
358
359
360 assertMaxPrecision(5.5, 1, false, "6", 0);
361 assertMaxPrecision(2.5, 1, false, "2", 0);
362 assertMaxPrecision(1.6, 1, false, "2", 0);
363 assertMaxPrecision(1.1, 1, false, "1", 0);
364 assertMaxPrecision(1.0, 1, false, "1", 0);
365
366 assertMaxPrecision(-1.0, 1, true, "1", 0);
367 assertMaxPrecision(-1.1, 1, true, "1", 0);
368 assertMaxPrecision(-1.6, 1, true, "2", 0);
369 assertMaxPrecision(-2.5, 1, true, "2", 0);
370 assertMaxPrecision(-5.5, 1, true, "6", 0);
371 }
372
373 @Test
374 void testMaxPrecision_random() {
375
376 final UniformRandomProvider rand = RandomSource.XO_RO_SHI_RO_128_PP.create(0L);
377 final ParsedDecimal.FormatOptions opts = new FormatOptionsImpl();
378
379 for (int i = 0; i < 10_000; ++i) {
380 final double d = createRandomDouble(rand);
381 final int precision = rand.nextInt(20) + 1;
382 final MathContext ctx = new MathContext(precision, RoundingMode.HALF_EVEN);
383
384 final ParsedDecimal dec = ParsedDecimal.from(d);
385
386
387 dec.maxPrecision(precision);
388
389
390 Assertions.assertEquals(new BigDecimal(Double.toString(d), ctx).doubleValue(),
391 Double.parseDouble(dec.toScientificString(opts)));
392 }
393 }
394
395 @Test
396 void testMaxPrecision_singleDigits() {
397
398 assertMaxPrecision(9.0, 1, false, "9", 0);
399 assertMaxPrecision(1.0, 1, false, "1", 0);
400 assertMaxPrecision(0.0, 1, false, "0", 0);
401 assertMaxPrecision(-0.0, 1, true, "0", 0);
402 assertMaxPrecision(-1.0, 1, true, "1", 0);
403 assertMaxPrecision(-9.0, 1, true, "9", 0);
404 }
405
406 @Test
407 void testRound_mixed() {
408
409 final double a = 9.94e-10;
410 final double b = -3.1415;
411 final double c = 5.55e10;
412
413
414 assertRound(a, -13, false, "994", -12);
415 assertRound(a, -12, false, "994", -12);
416 assertRound(a, -11, false, "99", -11);
417 assertRound(a, -10, false, "1", -9);
418 assertRound(a, -9, false, "1", -9);
419 assertRound(a, -8, false, "0", 0);
420
421 assertRound(b, -5, true, "31415", -4);
422 assertRound(b, -4, true, "31415", -4);
423 assertRound(b, -3, true, "3142", -3);
424 assertRound(b, -2, true, "314", -2);
425 assertRound(b, -1, true, "31", -1);
426 assertRound(b, 0, true, "3", 0);
427 assertRound(b, 1, true, "0", 0);
428 assertRound(b, 2, true, "0", 0);
429
430 assertRound(c, 7, false, "555", 8);
431 assertRound(c, 8, false, "555", 8);
432 assertRound(c, 9, false, "56", 9);
433 assertRound(c, 10, false, "6", 10);
434 assertRound(c, 11, false, "1", 11);
435 assertRound(c, 12, false, "0", 0);
436 }
437
438 @Test
439 void testRound_nine() {
440
441 final double a = 9e-10;
442 final double b = -9;
443 final double c = 9e10;
444
445
446 assertRound(a, -11, false, "9", -10);
447 assertRound(a, -10, false, "9", -10);
448 assertRound(a, -9, false, "1", -9);
449
450 assertRound(b, -1, true, "9", 0);
451 assertRound(b, 0, true, "9", 0);
452 assertRound(b, 1, true, "1", 1);
453
454 assertRound(c, 9, false, "9", 10);
455 assertRound(c, 10, false, "9", 10);
456 assertRound(c, 11, false, "1", 11);
457 }
458
459 @Test
460 void testRound_one() {
461
462 final double a = 1e-10;
463 final double b = -1;
464 final double c = 1e10;
465
466
467 assertRound(a, -11, false, "1", -10);
468 assertRound(a, -10, false, "1", -10);
469 assertRound(a, -9, false, "0", 0);
470
471 assertRound(b, -1, true, "1", 0);
472 assertRound(b, 0, true, "1", 0);
473 assertRound(b, 1, true, "0", 0);
474
475 assertRound(c, 9, false, "1", 10);
476 assertRound(c, 10, false, "1", 10);
477 assertRound(c, 11, false, "0", 0);
478 }
479
480 @Test
481 void testStringMethodAccuracy_random() {
482
483 final UniformRandomProvider rand = RandomSource.XO_RO_SHI_RO_128_PP.create(0L);
484
485 final FormatOptionsImpl stdOpts = new FormatOptionsImpl();
486 final FormatOptionsImpl altOpts = new FormatOptionsImpl();
487 altOpts.setExponentSeparator("e");
488 altOpts.setIncludeFractionPlaceholder(false);
489
490 double d;
491 for (int i = 0; i < 10_000; ++i) {
492 d = createRandomDouble(rand);
493
494
495 Assertions.assertEquals(d, Double.parseDouble(ParsedDecimal.from(d).toScientificString(stdOpts)));
496 Assertions.assertEquals(d, Double.parseDouble(ParsedDecimal.from(d).toScientificString(altOpts)));
497
498 Assertions.assertEquals(d, Double.parseDouble(ParsedDecimal.from(d).toEngineeringString(stdOpts)));
499 Assertions.assertEquals(d, Double.parseDouble(ParsedDecimal.from(d).toEngineeringString(altOpts)));
500
501 Assertions.assertEquals(d, Double.parseDouble(ParsedDecimal.from(d).toPlainString(stdOpts)));
502 Assertions.assertEquals(d, Double.parseDouble(ParsedDecimal.from(d).toPlainString(altOpts)));
503 }
504 }
505
506 @Test
507 void testStringMethodAccuracy_sequence() {
508
509 final double min = -1000;
510 final double max = 1000;
511 final double delta = 0.1;
512
513 final FormatOptionsImpl stdOpts = new FormatOptionsImpl();
514 final FormatOptionsImpl altOpts = new FormatOptionsImpl();
515 altOpts.setExponentSeparator("e");
516 altOpts.setIncludeFractionPlaceholder(false);
517
518 Assertions.assertEquals(10.0, Double.parseDouble(ParsedDecimal.from(10.0).toScientificString(stdOpts)));
519
520 for (double d = min; d <= max; d += delta) {
521
522 Assertions.assertEquals(d, Double.parseDouble(ParsedDecimal.from(d).toScientificString(stdOpts)));
523 Assertions.assertEquals(d, Double.parseDouble(ParsedDecimal.from(d).toScientificString(altOpts)));
524
525 Assertions.assertEquals(d, Double.parseDouble(ParsedDecimal.from(d).toEngineeringString(stdOpts)));
526 Assertions.assertEquals(d, Double.parseDouble(ParsedDecimal.from(d).toEngineeringString(altOpts)));
527
528 Assertions.assertEquals(d, Double.parseDouble(ParsedDecimal.from(d).toPlainString(stdOpts)));
529 Assertions.assertEquals(d, Double.parseDouble(ParsedDecimal.from(d).toPlainString(altOpts)));
530 }
531 }
532
533 @Test
534 void testStringMethods_customDigits() {
535
536 final FormatOptionsImpl opts = new FormatOptionsImpl();
537 opts.setDigitsFromString("abcdefghij");
538
539
540 Assertions.assertEquals("b.a", ParsedDecimal.from(1.0).toPlainString(opts));
541 Assertions.assertEquals("-a.abcd", ParsedDecimal.from(-0.0123).toPlainString(opts));
542 Assertions.assertEquals("bc.de", ParsedDecimal.from(12.34).toPlainString(opts));
543 Assertions.assertEquals("baaaa.a", ParsedDecimal.from(10000).toPlainString(opts));
544 Assertions.assertEquals("jihgfedcba.a", ParsedDecimal.from(9876543210d).toPlainString(opts));
545
546 Assertions.assertEquals("b.a", ParsedDecimal.from(1.0).toScientificString(opts));
547 Assertions.assertEquals("-b.cdE-c", ParsedDecimal.from(-0.0123).toScientificString(opts));
548 Assertions.assertEquals("b.cdeEb", ParsedDecimal.from(12.34).toScientificString(opts));
549 Assertions.assertEquals("b.aEe", ParsedDecimal.from(10000).toScientificString(opts));
550 Assertions.assertEquals("j.ihgfedcbEj", ParsedDecimal.from(9876543210d).toScientificString(opts));
551
552 Assertions.assertEquals("b.a", ParsedDecimal.from(1.0).toEngineeringString(opts));
553 Assertions.assertEquals("-bc.dE-d", ParsedDecimal.from(-0.0123).toEngineeringString(opts));
554 Assertions.assertEquals("bc.de", ParsedDecimal.from(12.34).toEngineeringString(opts));
555 Assertions.assertEquals("ba.aEd", ParsedDecimal.from(10000).toEngineeringString(opts));
556 Assertions.assertEquals("j.ihgfedcbEj", ParsedDecimal.from(9876543210d).toEngineeringString(opts));
557 }
558
559 @Test
560 void testToEngineeringString_altFormat() {
561
562 final FormatOptionsImpl opts = new FormatOptionsImpl();
563 opts.setIncludeFractionPlaceholder(false);
564 opts.setSignedZero(false);
565 opts.setDecimalSeparator(',');
566 opts.setMinusSign('!');
567 opts.setExponentSeparator("x10^");
568 opts.setAlwaysIncludeExponent(true);
569
570
571 checkToEngineeringString(0.0, "0x10^0", opts);
572 checkToEngineeringString(-0.0, "0x10^0", opts);
573 checkToEngineeringString(1.0, "1x10^0", opts);
574 checkToEngineeringString(1.5, "1,5x10^0", opts);
575
576 checkToEngineeringString(10, "10x10^0", opts);
577
578 checkToEngineeringString(-0.000000123, "!123x10^!9", opts);
579 checkToEngineeringString(12300000, "12,3x10^6", opts);
580
581 checkToEngineeringString(Math.PI, "3,141592653589793x10^0", opts);
582 checkToEngineeringString(Math.E, "2,718281828459045x10^0", opts);
583
584 checkToEngineeringString(-Double.MAX_VALUE, "!179,76931348623157x10^306", opts);
585 checkToEngineeringString(Double.MIN_VALUE, "4,9x10^!324", opts);
586 checkToEngineeringString(Double.MIN_NORMAL, "22,250738585072014x10^!309", opts);
587 }
588
589 @Test
590 void testToEngineeringString_defaults() {
591
592 final FormatOptionsImpl opts = new FormatOptionsImpl();
593
594
595 checkToEngineeringString(0.0, "0.0", opts);
596 checkToEngineeringString(-0.0, "-0.0", opts);
597 checkToEngineeringString(1.0, "1.0", opts);
598 checkToEngineeringString(1.5, "1.5", opts);
599
600 checkToEngineeringString(10, "10.0", opts);
601
602 checkToEngineeringString(-0.000000123, "-123.0E-9", opts);
603 checkToEngineeringString(12300000, "12.3E6", opts);
604
605 checkToEngineeringString(Math.PI, "3.141592653589793", opts);
606 checkToEngineeringString(Math.E, "2.718281828459045", opts);
607
608 checkToEngineeringString(-Double.MAX_VALUE, "-179.76931348623157E306", opts);
609 checkToEngineeringString(Double.MIN_VALUE, "4.9E-324", opts);
610 checkToEngineeringString(Double.MIN_NORMAL, "22.250738585072014E-309", opts);
611 }
612
613 @Test
614 void testToPlainString_altFormat() {
615
616 final FormatOptionsImpl opts = new FormatOptionsImpl();
617 opts.setIncludeFractionPlaceholder(false);
618 opts.setSignedZero(false);
619 opts.setDecimalSeparator(',');
620 opts.setMinusSign('!');
621 opts.setThousandsGroupingSeparator('_');
622 opts.setGroupThousands(true);
623
624
625 checkToPlainString(0.0, "0", opts);
626 checkToPlainString(-0.0, "0", opts);
627 checkToPlainString(1.0, "1", opts);
628 checkToPlainString(1.5, "1,5", opts);
629
630 checkToPlainString(12, "12", opts);
631 checkToPlainString(123, "123", opts);
632 checkToPlainString(1234, "1_234", opts);
633 checkToPlainString(12345, "12_345", opts);
634 checkToPlainString(123456, "123_456", opts);
635 checkToPlainString(1234567, "1_234_567", opts);
636 checkToPlainString(12345678, "12_345_678", opts);
637 checkToPlainString(123456789, "123_456_789", opts);
638 checkToPlainString(1234567890, "1_234_567_890", opts);
639
640 checkToPlainString(-0.000123, "!0,000123", opts);
641 checkToPlainString(12301, "12_301", opts);
642
643 checkToPlainString(Math.PI, "3,141592653589793", opts);
644 checkToPlainString(Math.E, "2,718281828459045", opts);
645
646 checkToPlainString(-12345.6789, "!12_345,6789", opts);
647 checkToPlainString(1.23e12, "1_230_000_000_000", opts);
648 checkToPlainString(1.23e-12, "0,00000000000123", opts);
649 }
650
651 @Test
652 void testToPlainString_defaults() {
653
654 final FormatOptionsImpl opts = new FormatOptionsImpl();
655
656
657 checkToPlainString(0.0, "0.0", opts);
658 checkToPlainString(-0.0, "-0.0", opts);
659 checkToPlainString(1.0, "1.0", opts);
660 checkToPlainString(1.5, "1.5", opts);
661
662 checkToPlainString(12, "12.0", opts);
663 checkToPlainString(123, "123.0", opts);
664 checkToPlainString(1234, "1234.0", opts);
665 checkToPlainString(12345, "12345.0", opts);
666 checkToPlainString(123456, "123456.0", opts);
667 checkToPlainString(1234567, "1234567.0", opts);
668 checkToPlainString(12345678, "12345678.0", opts);
669 checkToPlainString(123456789, "123456789.0", opts);
670 checkToPlainString(1234567890, "1234567890.0", opts);
671
672 checkToPlainString(-0.000123, "-0.000123", opts);
673 checkToPlainString(12301, "12301.0", opts);
674
675 checkToPlainString(Math.PI, "3.141592653589793", opts);
676 checkToPlainString(Math.E, "2.718281828459045", opts);
677
678 checkToPlainString(-12345.6789, "-12345.6789", opts);
679 checkToPlainString(1.23e12, "1230000000000.0", opts);
680 checkToPlainString(1.23e-12, "0.00000000000123", opts);
681 }
682
683 @Test
684 void testToScientificString_altFormats() {
685
686 final FormatOptionsImpl opts = new FormatOptionsImpl();
687 opts.setIncludeFractionPlaceholder(false);
688 opts.setSignedZero(false);
689 opts.setDecimalSeparator(',');
690 opts.setMinusSign('!');
691 opts.setExponentSeparator("x10^");
692 opts.setAlwaysIncludeExponent(true);
693
694
695 checkToScientificString(0.0, "0x10^0", opts);
696 checkToScientificString(-0.0, "0x10^0", opts);
697 checkToScientificString(1.0, "1x10^0", opts);
698 checkToScientificString(1.5, "1,5x10^0", opts);
699
700 checkToScientificString(-0.000123, "!1,23x10^!4", opts);
701 checkToScientificString(12301, "1,2301x10^4", opts);
702
703 checkToScientificString(Math.PI, "3,141592653589793x10^0", opts);
704 checkToScientificString(Math.E, "2,718281828459045x10^0", opts);
705
706 checkToScientificString(-Double.MAX_VALUE, "!1,7976931348623157x10^308", opts);
707 checkToScientificString(Double.MIN_VALUE, "4,9x10^!324", opts);
708 checkToScientificString(Double.MIN_NORMAL, "2,2250738585072014x10^!308", opts);
709 }
710
711 @Test
712 void testToScientificString_defaults() {
713
714 final FormatOptionsImpl opts = new FormatOptionsImpl();
715
716
717 checkToScientificString(0.0, "0.0", opts);
718 checkToScientificString(-0.0, "-0.0", opts);
719 checkToScientificString(1.0, "1.0", opts);
720 checkToScientificString(1.5, "1.5", opts);
721
722 checkToScientificString(-0.000123, "-1.23E-4", opts);
723 checkToScientificString(12301, "1.2301E4", opts);
724
725 checkToScientificString(Math.PI, "3.141592653589793", opts);
726 checkToScientificString(Math.E, "2.718281828459045", opts);
727
728 checkToScientificString(-Double.MAX_VALUE, "-1.7976931348623157E308", opts);
729 checkToScientificString(Double.MIN_VALUE, "4.9E-324", opts);
730 checkToScientificString(Double.MIN_NORMAL, "2.2250738585072014E-308", opts);
731 }
732 }