@@ -112,12 +112,21 @@ final class DigitList implements Cloneable {
112
112
* Return true if the represented number is zero.
113
113
*/
114
114
boolean isZero () {
115
- for (int i =0 ; i < count ; ++i ) {
115
+ return !nonZeroAfterIndex (0 );
116
+ }
117
+
118
+
119
+ /**
120
+ * Return true if there exists a non-zero digit in the digit list
121
+ * from the given index until the end.
122
+ */
123
+ private boolean nonZeroAfterIndex (int index ) {
124
+ for (int i =index ; i < count ; ++i ) {
116
125
if (digits [i ] != '0' ) {
117
- return false ;
126
+ return true ;
118
127
}
119
128
}
120
- return true ;
129
+ return false ;
121
130
}
122
131
123
132
/**
@@ -190,9 +199,7 @@ public final long getLong() {
190
199
191
200
StringBuilder temp = getStringBuilder ();
192
201
temp .append (digits , 0 , count );
193
- for (int i = count ; i < decimalAt ; ++i ) {
194
- temp .append ('0' );
195
- }
202
+ temp .append ("0" .repeat (Math .max (0 , decimalAt - count )));
196
203
return Long .parseLong (temp .toString ());
197
204
}
198
205
@@ -392,6 +399,17 @@ private void set(boolean isNegative, String s,
392
399
393
400
}
394
401
402
+ /**
403
+ * Round the representation to the given number of digits.
404
+ * @param maximumDigits The maximum number of digits to be shown.
405
+ *
406
+ * Upon return, count will be less than or equal to maximumDigits.
407
+ */
408
+ private void roundInt (int maximumDigits ) {
409
+ // Integers do not need to worry about double rounding
410
+ round (maximumDigits , false , true );
411
+ }
412
+
395
413
/**
396
414
* Round the representation to the given number of digits.
397
415
* @param maximumDigits The maximum number of digits to be shown.
@@ -408,25 +426,8 @@ private final void round(int maximumDigits,
408
426
// Round up if appropriate.
409
427
if (maximumDigits >= 0 && maximumDigits < count ) {
410
428
if (shouldRoundUp (maximumDigits , alreadyRounded , valueExactAsDecimal )) {
411
- // Rounding up involved incrementing digits from LSD to MSD.
412
- // In most cases this is simple, but in a worst case situation
413
- // (9999..99) we have to adjust the decimalAt value.
414
- for (;;) {
415
- --maximumDigits ;
416
- if (maximumDigits < 0 ) {
417
- // We have all 9's, so we increment to a single digit
418
- // of one and adjust the exponent.
419
- digits [0 ] = '1' ;
420
- ++decimalAt ;
421
- maximumDigits = 0 ; // Adjust the count
422
- break ;
423
- }
424
-
425
- ++digits [maximumDigits ];
426
- if (digits [maximumDigits ] <= '9' ) break ;
427
- // digits[maximumDigits] = '0'; // Unnecessary since we'll truncate this
428
- }
429
- ++maximumDigits ; // Increment for use as count
429
+ // Rounding can adjust the max digits
430
+ maximumDigits = roundUp (maximumDigits );
430
431
}
431
432
count = maximumDigits ;
432
433
@@ -508,94 +509,44 @@ private boolean shouldRoundUp(int maximumDigits,
508
509
509
510
switch (roundingMode ) {
510
511
case UP :
511
- for (int i =maximumDigits ; i <count ; ++i ) {
512
- if (digits [i ] != '0' ) {
513
- return true ;
514
- }
515
- }
516
- break ;
512
+ return nonZeroAfterIndex (maximumDigits );
517
513
case DOWN :
518
514
break ;
519
515
case CEILING :
520
- for (int i =maximumDigits ; i <count ; ++i ) {
521
- if (digits [i ] != '0' ) {
522
- return !isNegative ;
523
- }
524
- }
525
- break ;
516
+ return nonZeroAfterIndex (maximumDigits ) && !isNegative ;
526
517
case FLOOR :
527
- for (int i =maximumDigits ; i <count ; ++i ) {
528
- if (digits [i ] != '0' ) {
529
- return isNegative ;
530
- }
531
- }
532
- break ;
518
+ return nonZeroAfterIndex (maximumDigits ) && isNegative ;
533
519
case HALF_UP :
534
520
case HALF_DOWN :
535
- if (digits [maximumDigits ] > '5' ) {
536
- // Value is above tie ==> must round up
537
- return true ;
538
- } else if (digits [maximumDigits ] == '5' ) {
539
- // Digit at rounding position is a '5'. Tie cases.
540
- if (maximumDigits != (count - 1 )) {
541
- // There are remaining digits. Above tie => must round up
542
- return true ;
543
- } else {
544
- // Digit at rounding position is the last one !
545
- if (valueExactAsDecimal ) {
546
- // Exact binary representation. On the tie.
547
- // Apply rounding given by roundingMode.
548
- return roundingMode == RoundingMode .HALF_UP ;
549
- } else {
550
- // Not an exact binary representation.
551
- // Digit sequence either rounded up or truncated.
552
- // Round up only if it was truncated.
553
- return !alreadyRounded ;
554
- }
555
- }
556
- }
557
- // Digit at rounding position is < '5' ==> no round up.
558
- // Just let do the default, which is no round up (thus break).
559
- break ;
560
521
case HALF_EVEN :
561
- // Implement IEEE half-even rounding
522
+ // Above tie, round up for all cases
562
523
if (digits [maximumDigits ] > '5' ) {
563
524
return true ;
525
+ // At tie, consider UP, DOWN, and EVEN logic
564
526
} else if (digits [maximumDigits ] == '5' ) {
527
+ // Rounding position is the last index, there are 3 Cases.
565
528
if (maximumDigits == (count - 1 )) {
566
- // the rounding position is exactly the last index :
567
- if (alreadyRounded )
568
- // If FloatingDecimal rounded up (value was below tie),
569
- // then we should not round up again.
570
- return false ;
571
-
572
- if (!valueExactAsDecimal )
573
- // Otherwise if the digits don't represent exact value,
574
- // value was above tie and FloatingDecimal truncated
575
- // digits to tie. We must round up.
576
- return true ;
577
- else {
578
- // This is an exact tie value, and FloatingDecimal
579
- // provided all of the exact digits. We thus apply
580
- // HALF_EVEN rounding rule.
581
- return ((maximumDigits > 0 ) &&
582
- (digits [maximumDigits -1 ] % 2 != 0 ));
529
+ // When exact, consider specific contract logic
530
+ if (valueExactAsDecimal ) {
531
+ return (roundingMode == RoundingMode .HALF_UP ) ||
532
+ (roundingMode == RoundingMode .HALF_EVEN
533
+ && (maximumDigits > 0 ) && (digits [maximumDigits - 1 ] % 2 != 0 ));
534
+ // If already rounded, do not round again, otherwise round up
535
+ } else {
536
+ return !alreadyRounded ;
583
537
}
538
+ // Rounding position is not the last index
539
+ // If any further digits have a non-zero value, round up
584
540
} else {
585
- // Rounds up if it gives a non null digit after '5'
586
- for (int i =maximumDigits +1 ; i <count ; ++i ) {
587
- if (digits [i ] != '0' )
588
- return true ;
589
- }
541
+ return nonZeroAfterIndex (maximumDigits +1 );
590
542
}
591
543
}
544
+ // Below tie, do not round up for all cases
592
545
break ;
593
546
case UNNECESSARY :
594
- for (int i =maximumDigits ; i <count ; ++i ) {
595
- if (digits [i ] != '0' ) {
596
- throw new ArithmeticException (
547
+ if (nonZeroAfterIndex (maximumDigits )) {
548
+ throw new ArithmeticException (
597
549
"Rounding needed with the rounding mode being set to RoundingMode.UNNECESSARY" );
598
- }
599
550
}
600
551
break ;
601
552
default :
@@ -605,6 +556,33 @@ private boolean shouldRoundUp(int maximumDigits,
605
556
return false ;
606
557
}
607
558
559
+ /**
560
+ * Round the digit list up numerically.
561
+ * This involves incrementing digits from the LSD to the MSD.
562
+ * @param maximumDigits The maximum number of digits to be shown.
563
+ * @return The new maximum digits after rounding.
564
+ */
565
+ private int roundUp (int maximumDigits ) {
566
+ do {
567
+ --maximumDigits ;
568
+ /*
569
+ * We have exhausted the max digits while attempting to round up
570
+ * from the LSD to the MSD. This implies a value of all 9's. As such,
571
+ * adjust representation to a single digit of one and increment the exponent.
572
+ */
573
+ if (maximumDigits < 0 ) {
574
+ digits [0 ] = '1' ;
575
+ ++decimalAt ;
576
+ maximumDigits = 0 ; // Adjust the count
577
+ break ;
578
+ }
579
+ ++digits [maximumDigits ];
580
+ }
581
+ while (digits [maximumDigits ] > '9' );
582
+
583
+ return ++maximumDigits ; // Increment for use as count
584
+ }
585
+
608
586
/**
609
587
* Utility routine to set the value of the digit list from a long
610
588
*/
@@ -649,12 +627,16 @@ final void set(boolean isNegative, long source, int maximumDigits) {
649
627
decimalAt = MAX_COUNT - left ;
650
628
// Don't copy trailing zeros. We are guaranteed that there is at
651
629
// least one non-zero digit, so we don't have to check lower bounds.
652
- for (right = MAX_COUNT - 1 ; digits [right ] == '0' ; --right )
653
- ;
630
+ right = MAX_COUNT - 1 ;
631
+ while (digits [right ] == '0' ) {
632
+ --right ;
633
+ }
654
634
count = right - left + 1 ;
655
635
System .arraycopy (digits , left , digits , 0 , count );
656
636
}
657
- if (maximumDigits > 0 ) round (maximumDigits , false , true );
637
+ if (maximumDigits > 0 ) {
638
+ roundInt (maximumDigits );
639
+ }
658
640
}
659
641
660
642
/**
@@ -692,13 +674,14 @@ final void set(boolean isNegative, BigInteger source, int maximumDigits) {
692
674
s .getChars (0 , len , digits , 0 );
693
675
694
676
decimalAt = len ;
695
- int right ;
696
- for (right = len - 1 ; right >= 0 && digits [right ] == '0' ; --right )
697
- ;
677
+ int right = len - 1 ;
678
+ while (right >= 0 && digits [right ] == '0' ) {
679
+ --right ;
680
+ }
698
681
count = right + 1 ;
699
682
700
683
if (maximumDigits > 0 ) {
701
- round (maximumDigits , false , true );
684
+ roundInt (maximumDigits );
702
685
}
703
686
}
704
687
1 commit comments
openjdk-notifier[bot] commentedon Aug 17, 2023
Review
Issues