src/java.base/share/classes/java/text/DigitList.java

Print this page


   1 /*
   2  * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


 292         boolean hasBeenRoundedUp = fdConverter.digitsRoundedUp();
 293         boolean allDecimalDigits = fdConverter.decimalDigitsExact();
 294         assert !fdConverter.isExceptional();
 295         String digitsString = fdConverter.toJavaFormatString();
 296 
 297         set(isNegative, digitsString,
 298             hasBeenRoundedUp, allDecimalDigits,
 299             maximumDigits, fixedPoint);
 300     }
 301 
 302     /**
 303      * Generate a representation of the form DDDDD, DDDDD.DDDDD, or
 304      * DDDDDE+/-DDDDD.
 305      * @param roundedUp Boolean value indicating if the s digits were rounded-up.
 306      * @param allDecimalDigits Boolean value indicating if the digits in s are
 307      * an exact decimal representation of the double that was passed.
 308      */
 309     private void set(boolean isNegative, String s,
 310                      boolean roundedUp, boolean allDecimalDigits,
 311                      int maximumDigits, boolean fixedPoint) {

 312         this.isNegative = isNegative;
 313         int len = s.length();
 314         char[] source = getDataChars(len);
 315         s.getChars(0, len, source, 0);
 316 
 317         decimalAt = -1;
 318         count = 0;
 319         int exponent = 0;
 320         // Number of zeros between decimal point and first non-zero digit after
 321         // decimal point, for numbers < 1.
 322         int leadingZerosAfterDecimal = 0;
 323         boolean nonZeroDigitSeen = false;
 324 
 325         for (int i = 0; i < len; ) {
 326             char c = source[i++];
 327             if (c == '.') {
 328                 decimalAt = count;
 329             } else if (c == 'e' || c == 'E') {
 330                 exponent = parseInt(source, i, len);
 331                 break;


 365                     count = 1;
 366                     ++decimalAt;
 367                     digits[0] = '1';
 368                 } else {
 369                     count = 0;
 370                 }
 371                 return;
 372             }
 373             // else fall through
 374         }
 375 
 376         // Eliminate trailing zeros.
 377         while (count > 1 && digits[count - 1] == '0') {
 378             --count;
 379         }
 380 
 381         // Eliminate digits beyond maximum digits to be displayed.
 382         // Round up if appropriate.
 383         round(fixedPoint ? (maximumDigits + decimalAt) : maximumDigits,
 384               roundedUp, allDecimalDigits);

 385     }
 386 
 387     /**
 388      * Round the representation to the given number of digits.
 389      * @param maximumDigits The maximum number of digits to be shown.
 390      * @param alreadyRounded Boolean indicating if rounding up already happened.
 391      * @param allDecimalDigits Boolean indicating if the digits provide an exact
 392      * representation of the value.
 393      *
 394      * Upon return, count will be less than or equal to maximumDigits.
 395      */
 396     private final void round(int maximumDigits,
 397                              boolean alreadyRounded,
 398                              boolean allDecimalDigits) {
 399         // Eliminate digits beyond maximum digits to be displayed.
 400         // Round up if appropriate.
 401         if (maximumDigits >= 0 && maximumDigits < count) {
 402             if (shouldRoundUp(maximumDigits, alreadyRounded, allDecimalDigits)) {
 403                 // Rounding up involved incrementing digits from LSD to MSD.
 404                 // In most cases this is simple, but in a worst case situation


 423             count = maximumDigits;
 424 
 425             // Eliminate trailing zeros.
 426             while (count > 1 && digits[count-1] == '0') {
 427                 --count;
 428             }
 429         }
 430     }
 431 
 432 
 433     /**
 434      * Return true if truncating the representation to the given number
 435      * of digits will result in an increment to the last digit.  This
 436      * method implements the rounding modes defined in the
 437      * java.math.RoundingMode class.
 438      * [bnf]
 439      * @param maximumDigits the number of digits to keep, from 0 to
 440      * <code>count-1</code>.  If 0, then all digits are rounded away, and
 441      * this method returns true if a one should be generated (e.g., formatting
 442      * 0.09 with "#.#").



 443      * @exception ArithmeticException if rounding is needed with rounding
 444      *            mode being set to RoundingMode.UNNECESSARY
 445      * @return true if digit <code>maximumDigits-1</code> should be
 446      * incremented
 447      */
 448     private boolean shouldRoundUp(int maximumDigits,
 449                                   boolean alreadyRounded,
 450                                   boolean allDecimalDigits) {
 451         if (maximumDigits < count) {
 452             /*
 453              * To avoid erroneous double-rounding or truncation when converting
 454              * a binary double value to text, information about the exactness
 455              * of the conversion result in FloatingDecimal, as well as any
 456              * rounding done, is needed in this class.
 457              *
 458              * - For the  HALF_DOWN, HALF_EVEN, HALF_UP rounding rules below:
 459              *   In the case of formating float or double, We must take into
 460              *   account what FloatingDecimal has done in the binary to decimal
 461              *   conversion.
 462              *


 503                     }
 504                 }
 505                 break;
 506             case DOWN:
 507                 break;
 508             case CEILING:
 509                 for (int i=maximumDigits; i<count; ++i) {
 510                     if (digits[i] != '0') {
 511                         return !isNegative;
 512                     }
 513                 }
 514                 break;
 515             case FLOOR:
 516                 for (int i=maximumDigits; i<count; ++i) {
 517                     if (digits[i] != '0') {
 518                         return isNegative;
 519                     }
 520                 }
 521                 break;
 522             case HALF_UP:
 523                 if (digits[maximumDigits] >= '5') {
 524                     // We should not round up if the rounding digits position is
 525                     // exactly the last index and if digits were already rounded.
 526                     if ((maximumDigits == (count - 1)) &&
 527                         (alreadyRounded))
 528                         return false;
 529 
 530                     // Value was exactly at or was above tie. We must round up.
 531                     return true;
 532                 }
 533                 break;
 534             case HALF_DOWN:
 535                 if (digits[maximumDigits] > '5') {

 536                     return true;
 537                 } else if (digits[maximumDigits] == '5' ) {
 538                     if (maximumDigits == (count - 1)) {
 539                         // The rounding position is exactly the last index.
 540                         if (allDecimalDigits || alreadyRounded)
 541                             /* FloatingDecimal rounded up (value was below tie),
 542                              * or provided the exact list of digits (value was
 543                              * an exact tie). We should not round up, following
 544                              * the HALF_DOWN rounding rule.
 545                              */
 546                             return false;
 547                         else
 548                             // Value was above the tie, we must round up.
 549                             return true;
 550                     }
 551 
 552                     // We must round up if it gives a non null digit after '5'.
 553                     for (int i=maximumDigits+1; i<count; ++i) {
 554                         if (digits[i] != '0') {


 555                             return true;
 556                         }


















 557                     }
 558                 }


 559                 break;
 560             case HALF_EVEN:
 561                 // Implement IEEE half-even rounding
 562                 if (digits[maximumDigits] > '5') {
 563                     return true;
 564                 } else if (digits[maximumDigits] == '5' ) {
 565                     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 (!allDecimalDigits)
 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


   1 /*
   2  * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


 292         boolean hasBeenRoundedUp = fdConverter.digitsRoundedUp();
 293         boolean allDecimalDigits = fdConverter.decimalDigitsExact();
 294         assert !fdConverter.isExceptional();
 295         String digitsString = fdConverter.toJavaFormatString();
 296 
 297         set(isNegative, digitsString,
 298             hasBeenRoundedUp, allDecimalDigits,
 299             maximumDigits, fixedPoint);
 300     }
 301 
 302     /**
 303      * Generate a representation of the form DDDDD, DDDDD.DDDDD, or
 304      * DDDDDE+/-DDDDD.
 305      * @param roundedUp Boolean value indicating if the s digits were rounded-up.
 306      * @param allDecimalDigits Boolean value indicating if the digits in s are
 307      * an exact decimal representation of the double that was passed.
 308      */
 309     private void set(boolean isNegative, String s,
 310                      boolean roundedUp, boolean allDecimalDigits,
 311                      int maximumDigits, boolean fixedPoint) {
 312 
 313         this.isNegative = isNegative;
 314         int len = s.length();
 315         char[] source = getDataChars(len);
 316         s.getChars(0, len, source, 0);
 317 
 318         decimalAt = -1;
 319         count = 0;
 320         int exponent = 0;
 321         // Number of zeros between decimal point and first non-zero digit after
 322         // decimal point, for numbers < 1.
 323         int leadingZerosAfterDecimal = 0;
 324         boolean nonZeroDigitSeen = false;
 325 
 326         for (int i = 0; i < len; ) {
 327             char c = source[i++];
 328             if (c == '.') {
 329                 decimalAt = count;
 330             } else if (c == 'e' || c == 'E') {
 331                 exponent = parseInt(source, i, len);
 332                 break;


 366                     count = 1;
 367                     ++decimalAt;
 368                     digits[0] = '1';
 369                 } else {
 370                     count = 0;
 371                 }
 372                 return;
 373             }
 374             // else fall through
 375         }
 376 
 377         // Eliminate trailing zeros.
 378         while (count > 1 && digits[count - 1] == '0') {
 379             --count;
 380         }
 381 
 382         // Eliminate digits beyond maximum digits to be displayed.
 383         // Round up if appropriate.
 384         round(fixedPoint ? (maximumDigits + decimalAt) : maximumDigits,
 385               roundedUp, allDecimalDigits);
 386 
 387      }
 388 
 389     /**
 390      * Round the representation to the given number of digits.
 391      * @param maximumDigits The maximum number of digits to be shown.
 392      * @param alreadyRounded Boolean indicating if rounding up already happened.
 393      * @param allDecimalDigits Boolean indicating if the digits provide an exact
 394      * representation of the value.
 395      *
 396      * Upon return, count will be less than or equal to maximumDigits.
 397      */
 398     private final void round(int maximumDigits,
 399                              boolean alreadyRounded,
 400                              boolean allDecimalDigits) {
 401         // Eliminate digits beyond maximum digits to be displayed.
 402         // Round up if appropriate.
 403         if (maximumDigits >= 0 && maximumDigits < count) {
 404             if (shouldRoundUp(maximumDigits, alreadyRounded, allDecimalDigits)) {
 405                 // Rounding up involved incrementing digits from LSD to MSD.
 406                 // In most cases this is simple, but in a worst case situation


 425             count = maximumDigits;
 426 
 427             // Eliminate trailing zeros.
 428             while (count > 1 && digits[count-1] == '0') {
 429                 --count;
 430             }
 431         }
 432     }
 433 
 434 
 435     /**
 436      * Return true if truncating the representation to the given number
 437      * of digits will result in an increment to the last digit.  This
 438      * method implements the rounding modes defined in the
 439      * java.math.RoundingMode class.
 440      * [bnf]
 441      * @param maximumDigits the number of digits to keep, from 0 to
 442      * <code>count-1</code>.  If 0, then all digits are rounded away, and
 443      * this method returns true if a one should be generated (e.g., formatting
 444      * 0.09 with "#.#").
 445      * @param alreadyRounded Boolean indicating if rounding up already happened.
 446      * @param allDecimalDigits Boolean indicating if the digits provide an exact
 447      * representation of the value.
 448      * @exception ArithmeticException if rounding is needed with rounding
 449      *            mode being set to RoundingMode.UNNECESSARY
 450      * @return true if digit <code>maximumDigits-1</code> should be
 451      * incremented
 452      */
 453     private boolean shouldRoundUp(int maximumDigits,
 454                                   boolean alreadyRounded,
 455                                   boolean allDecimalDigits) {
 456         if (maximumDigits < count) {
 457             /*
 458              * To avoid erroneous double-rounding or truncation when converting
 459              * a binary double value to text, information about the exactness
 460              * of the conversion result in FloatingDecimal, as well as any
 461              * rounding done, is needed in this class.
 462              *
 463              * - For the  HALF_DOWN, HALF_EVEN, HALF_UP rounding rules below:
 464              *   In the case of formating float or double, We must take into
 465              *   account what FloatingDecimal has done in the binary to decimal
 466              *   conversion.
 467              *


 508                     }
 509                 }
 510                 break;
 511             case DOWN:
 512                 break;
 513             case CEILING:
 514                 for (int i=maximumDigits; i<count; ++i) {
 515                     if (digits[i] != '0') {
 516                         return !isNegative;
 517                     }
 518                 }
 519                 break;
 520             case FLOOR:
 521                 for (int i=maximumDigits; i<count; ++i) {
 522                     if (digits[i] != '0') {
 523                         return isNegative;
 524                     }
 525                 }
 526                 break;
 527             case HALF_UP:











 528             case HALF_DOWN:
 529                 if (digits[maximumDigits] > '5') {
 530                     // Value is above tie ==> must round-up
 531                     return true;
 532                 }
 533                 else if (digits[maximumDigits] == '5') {
 534                     // Digit at rounding position is a '5'. Tie cases.
 535                     if (maximumDigits != (count - 1)) {
 536                         // There are remaining digits. Above tie => must round-up







 537                         return true;
 538                     }
 539                     else {
 540                         // Digit at rounding position is the last one !
 541                         if (allDecimalDigits) {
 542                             // Exact binary representation. On the tie.
 543                             if (roundingMode == RoundingMode.HALF_UP) {
 544                                 // Strictly follow HALF_UP rule ==> round-up
 545                                 return true;
 546                             }
 547                             else {
 548                                 // Strictly follow HALF_DOWN rule ==> don't round-up
 549                                 return false;
 550                             }
 551                         }
 552                         else {
 553                             // Not an exact binary representation.
 554                             if (alreadyRounded) {
 555                                 // Digit sequence rounded-up. Was below tie.
 556                                 // Don't round-up twice !
 557                                 return false;
 558                             }
 559                             else {
 560                                 // Digit sequence truncated. Was above tie.
 561                                 // must round-up !
 562                                 return true;
 563                             }
 564                         }
 565                     }
 566                 }
 567                 // Digit at rounding position is < '5' ==> no round-up.
 568                 // Just let do the default, which is no round-up (thus break).
 569                 break;
 570             case HALF_EVEN:
 571                 // Implement IEEE half-even rounding
 572                 if (digits[maximumDigits] > '5') {
 573                     return true;
 574                 } else if (digits[maximumDigits] == '5' ) {
 575                     if (maximumDigits == (count - 1)) {
 576                         // the rounding position is exactly the last index :
 577                         if (alreadyRounded)
 578                             // If FloatingDecimal rounded up (value was below tie),
 579                             // then we should not round up again.
 580                             return false;
 581 
 582                         if (!allDecimalDigits)
 583                             // Otherwise if the digits don't represent exact value,
 584                             // value was above tie and FloatingDecimal truncated
 585                             // digits to tie. We must round up.
 586                             return true;
 587                         else {
 588                             // This is an exact tie value, and FloatingDecimal