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
|