/** *Utilityroutinetogetthevalueofthedigitlist. *If(count==0)thisreturns0, *unlikeLong.parseLong("")whichthrowsNumberFormatException.
*/ publicfinallong getLong() { // for now, simple implementation; later, do proper IEEE native stuff
if (count == 0) { return0;
}
// We have to check for this, because this is the one NEGATIVE value // we represent. If we tried to just pass the digits off to parseLong, // we'd get a parse failure. if (isLongMIN_VALUE()) { returnLong.MIN_VALUE;
}
StringBuilder temp = getStringBuilder();
temp.append(digits, 0, count); for (int i = count; i < decimalAt; ++i) {
temp.append('0');
} returnLong.parseLong(temp.toString());
}
/** *Returntrueifthenumberrepresentedbythisobjectcanfitinto *along. *@paramisPositivetrueifthisnumbershouldberegardedaspositive *@paramignoreNegativeZerotrueif-0shouldberegardedasidenticalto *+0;otherwisetheyareconsidereddistinct *@returntrueifthisnumberfitsintoaJavalong
*/ boolean fitsIntoLong(boolean isPositive, boolean ignoreNegativeZero) { // Figure out if the result will fit in a long. We have to // first look for nonzero digits after the decimal point; // then check the size. If the digit count is 18 or less, then // the value can definitely be represented as a long. If it is 19 // then it may be too large.
// Trim trailing zeros. This does not change the represented value. while (count > 0 && digits[count - 1] == '0') {
--count;
}
if (count == 0) { // Positive zero fits into a long, but negative zero can only // be represented as a double. - bug 4162852 return isPositive || ignoreNegativeZero;
}
// At this point we have decimalAt == count, and count == MAX_COUNT. // The number will overflow if it is larger than 9223372036854775807 // or smaller than -9223372036854775808. for (int i=0; i<count; ++i) { char dig = digits[i], max = LONG_MIN_REP[i]; if (dig > max) returnfalse; if (dig < max) returntrue;
}
// At this point the first count digits match. If decimalAt is less // than count, then the remaining digits are zero, and we return true. if (count < decimalAt) returntrue;
// Now we have a representation of Long.MIN_VALUE, without the leading // negative sign. If this represents a positive value, then it does // not fit; otherwise it fits. return !isPositive;
}
this.isNegative = isNegative; int len = s.length(); char[] source = getDataChars(len);
s.getChars(0, len, source, 0);
decimalAt = -1;
count = 0; int exponent = 0; // Number of zeros between decimal point and first non-zero digit after // decimal point, for numbers < 1. int leadingZerosAfterDecimal = 0; boolean nonZeroDigitSeen = false;
for (int i = 0; i < len; ) { char c = source[i++]; if (c == '.') {
decimalAt = count;
} elseif (c == 'e' || c == 'E') {
exponent = parseInt(source, i, len); break;
} else { if (!nonZeroDigitSeen) {
nonZeroDigitSeen = (c != '0'); if (!nonZeroDigitSeen && decimalAt != -1)
++leadingZerosAfterDecimal;
} if (nonZeroDigitSeen) {
digits[count++] = c;
}
}
} if (decimalAt == -1) {
decimalAt = count;
} if (nonZeroDigitSeen) {
decimalAt += exponent - leadingZerosAfterDecimal;
}
if (fixedPoint) { // The negative of the exponent represents the number of leading // zeros between the decimal and the first non-zero digit, for // a value < 0.1 (e.g., for 0.00123, -decimalAt == 2). If this // is more than the maximum fraction digits, then we have an underflow // for the printed representation. if (-decimalAt > maximumDigits) { // Handle an underflow to zero when we round something like // 0.0009 to 2 fractional digits.
count = 0; return;
} elseif (-decimalAt == maximumDigits) { // If we round 0.0009 to 3 fractional digits, then we have to // create a new one digit in the least significant location. if (shouldRoundUp(0, roundedUp, valueExactAsDecimal)) {
count = 1;
++decimalAt;
digits[0] = '1';
} else {
count = 0;
} return;
} // else fall through
}
// Eliminate digits beyond maximum digits to be displayed. // Round up if appropriate.
round(fixedPoint ? (maximumDigits + decimalAt) : maximumDigits,
roundedUp, valueExactAsDecimal);
}
/** *Roundtherepresentationtothegivennumberofdigits. *@parammaximumDigitsThemaximumnumberofdigitstobeshown. *@paramalreadyRoundedwhetherornotroundinguphasalreadyhappened. *@paramvalueExactAsDecimalwhetherornotcollecteddigitsprovide *anexactdecimalrepresentationofthevalue. * *Uponreturn,countwillbelessthanorequaltomaximumDigits.
*/ privatefinalvoid round(int maximumDigits, boolean alreadyRounded, boolean valueExactAsDecimal) { // Eliminate digits beyond maximum digits to be displayed. // Round up if appropriate. if (maximumDigits >= 0 && maximumDigits < count) { if (shouldRoundUp(maximumDigits, alreadyRounded, valueExactAsDecimal)) { // Rounding up involved incrementing digits from LSD to MSD. // In most cases this is simple, but in a worst case situation // (9999..99) we have to adjust the decimalAt value. for (;;) {
--maximumDigits; if (maximumDigits < 0) { // We have all 9's, so we increment to a single digit // of one and adjust the exponent.
digits[0] = '1';
++decimalAt;
maximumDigits = 0; // Adjust the count break;
}
++digits[maximumDigits]; if (digits[maximumDigits] <= '9') break; // digits[maximumDigits] = '0'; // Unnecessary since we'll truncate this
}
++maximumDigits; // Increment for use as count
}
count = maximumDigits;
switch(roundingMode) { case UP: for (int i=maximumDigits; i<count; ++i) { if (digits[i] != '0') { returntrue;
}
} break; case DOWN: break; case CEILING: for (int i=maximumDigits; i<count; ++i) { if (digits[i] != '0') { return !isNegative;
}
} break; case FLOOR: for (int i=maximumDigits; i<count; ++i) { if (digits[i] != '0') { return isNegative;
}
} break; case HALF_UP: case HALF_DOWN: if (digits[maximumDigits] > '5') { // Value is above tie ==> must round up returntrue;
} elseif (digits[maximumDigits] == '5') { // Digit at rounding position is a '5'. Tie cases. if (maximumDigits != (count - 1)) { // There are remaining digits. Above tie => must round up returntrue;
} else { // Digit at rounding position is the last one ! if (valueExactAsDecimal) { // Exact binary representation. On the tie. // Apply rounding given by roundingMode. return roundingMode == RoundingMode.HALF_UP;
} else { // Not an exact binary representation. // Digit sequence either rounded up or truncated. // Round up only if it was truncated. return !alreadyRounded;
}
}
} // Digit at rounding position is < '5' ==> no round up. // Just let do the default, which is no round up (thus break). break; case HALF_EVEN: // Implement IEEE half-even rounding if (digits[maximumDigits] > '5') { returntrue;
} elseif (digits[maximumDigits] == '5' ) { if (maximumDigits == (count - 1)) { // the rounding position is exactly the last index : if (alreadyRounded) // If FloatingDecimal rounded up (value was below tie), // then we should not round up again. returnfalse;
if (!valueExactAsDecimal) // Otherwise if the digits don't represent exact value, // value was above tie and FloatingDecimal truncated // digits to tie. We must round up. returntrue; else { // This is an exact tie value, and FloatingDecimal // provided all of the exact digits. We thus apply // HALF_EVEN rounding rule. return ((maximumDigits > 0) &&
(digits[maximumDigits-1] % 2 != 0));
}
} else { // Rounds up if it gives a non null digit after '5' for (int i=maximumDigits+1; i<count; ++i) { if (digits[i] != '0') returntrue;
}
}
} break; case UNNECESSARY: for (int i=maximumDigits; i<count; ++i) { if (digits[i] != '0') { thrownew ArithmeticException( "Rounding needed with the rounding mode being set to RoundingMode.UNNECESSARY");
}
} break; default: assertfalse;
}
} returnfalse;
}
/** *Setthedigitlisttoarepresentationofthegivenlongvalue. *@paramisNegativeBooleanvalueindicatingwhetherthenumberisnegative. *@paramsourceValuetobeconverted;mustbe>=0or== *Long.MIN_VALUE. *@parammaximumDigitsThemostdigitswhichshouldbeconverted. *IfmaximumDigitsislowerthanthenumberofsignificantdigits *insource,therepresentationwillberounded.Ignoredif<=0.
*/ finalvoid set(boolean isNegative, long source, int maximumDigits) { this.isNegative = isNegative;
// This method does not expect a negative number. However, // "source" can be a Long.MIN_VALUE (-9223372036854775808), // if the number being formatted is a Long.MIN_VALUE. In that // case, it will be formatted as -Long.MIN_VALUE, a number // which is outside the legal range of a long, but which can // be represented by DigitList. if (source <= 0) { if (source == Long.MIN_VALUE) {
decimalAt = count = MAX_COUNT;
System.arraycopy(LONG_MIN_REP, 0, digits, 0, count);
} else {
decimalAt = count = 0; // Values <= 0 format as zero
}
} else { // Rewritten to improve performance. I used to call // Long.toString(), which was about 4x slower than this code. int left = MAX_COUNT; int right; while (source > 0) {
digits[--left] = (char)('0' + (source % 10));
source /= 10;
}
decimalAt = MAX_COUNT - left; // Don't copy trailing zeros. We are guaranteed that there is at // least one non-zero digit, so we don't have to check lower bounds. for (right = MAX_COUNT - 1; digits[right] == '0'; --right)
;
count = right - left + 1;
System.arraycopy(digits, left, digits, 0, count);
} if (maximumDigits > 0) round(maximumDigits, false, true);
}
int value = 0; while (offset < strLen) {
c = str[offset++]; if (c >= '0' && c <= '9') {
value = value * 10 + (c - '0');
} else { break;
}
} return positive ? value : -value;
}
// The digit part of -9223372036854775808L privatestaticfinalchar[] LONG_MIN_REP = "9223372036854775808".toCharArray();
public String toString() { if (isZero()) { return"0";
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.