📄 dtoa.java
字号:
d *= 10.0; if (d == 0) break; } return k + 1; } m2 = b2; m5 = b5; mhi = mlo = null; if (leftright) { if (mode < 2) { i = (denorm) ? be[0] + (Bias + (P-1) - 1 + 1) : 1 + P - bbits[0]; /* i is 1 plus the number of trailing zero bits in d's significand. Thus, (2^m2 * 5^m5) / (2^(s2+i) * 5^s5) = (1/2 lsb of d)/10^k. */ } else { j = ilim - 1; if (m5 >= j) m5 -= j; else { s5 += j -= m5; b5 += j; m5 = 0; } if ((i = ilim) < 0) { m2 -= i; i = 0; } /* (2^m2 * 5^m5) / (2^(s2+i) * 5^s5) = (1/2 * 10^(1-ilim))/10^k. */ } b2 += i; s2 += i; mhi = BigInteger.valueOf(1); /* (mhi * 2^m2 * 5^m5) / (2^s2 * 5^s5) = one-half of last printed (when mode >= 2) or input (when mode < 2) significant digit, divided by 10^k. */ } /* We still have d/10^k = (b * 2^b2 * 5^b5) / (2^s2 * 5^s5). Reduce common factors in b2, m2, and s2 without changing the equalities. */ if (m2 > 0 && s2 > 0) { i = (m2 < s2) ? m2 : s2; b2 -= i; m2 -= i; s2 -= i; } /* Fold b5 into b and m5 into mhi. */ if (b5 > 0) { if (leftright) { if (m5 > 0) { mhi = pow5mult(mhi, m5); b1 = mhi.multiply(b); b = b1; } if ((j = b5 - m5) != 0) b = pow5mult(b, j); } else b = pow5mult(b, b5); } /* Now we have d/10^k = (b * 2^b2) / (2^s2 * 5^s5) and (mhi * 2^m2) / (2^s2 * 5^s5) = one-half of last printed or input significant digit, divided by 10^k. */ S = BigInteger.valueOf(1); if (s5 > 0) S = pow5mult(S, s5); /* Now we have d/10^k = (b * 2^b2) / (S * 2^s2) and (mhi * 2^m2) / (S * 2^s2) = one-half of last printed or input significant digit, divided by 10^k. */ /* Check for special case that d is a normalized power of 2. */ spec_case = false; if (mode < 2) { if ( (word1(d) == 0) && ((word0(d) & Bndry_mask) == 0) && ((word0(d) & (Exp_mask & Exp_mask << 1)) != 0) ) { /* The special case. Here we want to be within a quarter of the last input significant digit instead of one half of it when the decimal output string's value is less than d. */ b2 += Log2P; s2 += Log2P; spec_case = true; } } /* Arrange for convenient computation of quotients: * shift left if necessary so divisor has 4 leading 0 bits. * * Perhaps we should just compute leading 28 bits of S once * and for all and pass them and a shift to quorem, so it * can do shifts and ors to compute the numerator for q. */ byte [] S_bytes = S.toByteArray(); int S_hiWord = 0; for (int idx = 0; idx < 4; idx++) { S_hiWord = (S_hiWord << 8); if (idx < S_bytes.length) S_hiWord |= (S_bytes[idx] & 0xFF); } if ((i = (((s5 != 0) ? 32 - hi0bits(S_hiWord) : 1) + s2) & 0x1f) != 0) i = 32 - i; /* i is the number of leading zero bits in the most significant word of S*2^s2. */ if (i > 4) { i -= 4; b2 += i; m2 += i; s2 += i; } else if (i < 4) { i += 28; b2 += i; m2 += i; s2 += i; } /* Now S*2^s2 has exactly four leading zero bits in its most significant word. */ if (b2 > 0) b = b.shiftLeft(b2); if (s2 > 0) S = S.shiftLeft(s2); /* Now we have d/10^k = b/S and (mhi * 2^m2) / S = maximum acceptable error, divided by 10^k. */ if (k_check) { if (b.compareTo(S) < 0) { k--; b = b.multiply(BigInteger.valueOf(10)); /* we botched the k estimate */ if (leftright) mhi = mhi.multiply(BigInteger.valueOf(10)); ilim = ilim1; } } /* At this point 1 <= d/10^k = b/S < 10. */ if (ilim <= 0 && mode > 2) { /* We're doing fixed-mode output and d is less than the minimum nonzero output in this mode. Output either zero or the minimum nonzero output depending on which is closer to d. */ if ((ilim < 0 ) || ((i = b.compareTo(S = S.multiply(BigInteger.valueOf(5)))) < 0) || ((i == 0 && !biasUp))) { /* Always emit at least one digit. If the number appears to be zero using the current mode, then emit one '0' digit and set decpt to 1. */ /*no_digits: k = -1 - ndigits; goto ret; */ buf.setLength(0); buf.append('0'); /* copy "0" to buffer */ return 1;// goto no_digits; }// one_digit: buf.append('1'); k++; return k + 1; } if (leftright) { if (m2 > 0) mhi = mhi.shiftLeft(m2); /* Compute mlo -- check for special case * that d is a normalized power of 2. */ mlo = mhi; if (spec_case) { mhi = mlo; mhi = mhi.shiftLeft(Log2P); } /* mlo/S = maximum acceptable error, divided by 10^k, if the output is less than d. */ /* mhi/S = maximum acceptable error, divided by 10^k, if the output is greater than d. */ for(i = 1;;i++) { BigInteger[] divResult = b.divideAndRemainder(S); b = divResult[1]; dig = (char)(divResult[0].intValue() + '0'); /* Do we yet have the shortest decimal string * that will round to d? */ j = b.compareTo(mlo); /* j is b/S compared with mlo/S. */ delta = S.subtract(mhi); j1 = (delta.signum() <= 0) ? 1 : b.compareTo(delta); /* j1 is b/S compared with 1 - mhi/S. */ if ((j1 == 0) && (mode == 0) && ((word1(d) & 1) == 0)) { if (dig == '9') { buf.append('9'); if (roundOff(buf)) { k++; buf.append('1'); } return k + 1;// goto round_9_up; } if (j > 0) dig++; buf.append(dig); return k + 1; } if ((j < 0) || ((j == 0) && (mode == 0) && ((word1(d) & 1) == 0) )) { if (j1 > 0) { /* Either dig or dig+1 would work here as the least significant decimal digit. Use whichever would produce a decimal value closer to d. */ b = b.shiftLeft(1); j1 = b.compareTo(S); if (((j1 > 0) || (j1 == 0 && (((dig & 1) == 1) || biasUp))) && (dig++ == '9')) { buf.append('9'); if (roundOff(buf)) { k++; buf.append('1'); } return k + 1;// goto round_9_up; } } buf.append(dig); return k + 1; } if (j1 > 0) { if (dig == '9') { /* possible if i == 1 */// round_9_up:// *s++ = '9';// goto roundoff; buf.append('9'); if (roundOff(buf)) { k++; buf.append('1'); } return k + 1; } buf.append((char)(dig + 1)); return k + 1; } buf.append(dig); if (i == ilim) break; b = b.multiply(BigInteger.valueOf(10)); if (mlo == mhi) mlo = mhi = mhi.multiply(BigInteger.valueOf(10)); else { mlo = mlo.multiply(BigInteger.valueOf(10)); mhi = mhi.multiply(BigInteger.valueOf(10)); } } } else for(i = 1;; i++) {// (char)(dig = quorem(b,S) + '0'); BigInteger[] divResult = b.divideAndRemainder(S); b = divResult[1]; dig = (char)(divResult[0].intValue() + '0'); buf.append(dig); if (i >= ilim) break; b = b.multiply(BigInteger.valueOf(10)); } /* Round off last digit */ b = b.shiftLeft(1); j = b.compareTo(S); if ((j > 0) || (j == 0 && (((dig & 1) == 1) || biasUp))) {// roundoff:// while(*--s == '9')// if (s == buf) {// k++;// *s++ = '1';// goto ret;// }// ++*s++; if (roundOff(buf)) { k++; buf.append('1'); return k + 1; } } else { /* Strip trailing zeros */ while (buf.charAt(buf.length() - 1) == '0') buf.setLength(buf.length() - 1);// while(*--s == '0') ;// s++; }// ret:// Bfree(S);// if (mhi) {// if (mlo && mlo != mhi)// Bfree(mlo);// Bfree(mhi);// }// ret1:// Bfree(b);// JS_ASSERT(s < buf + bufsize); return k + 1; } /* Mapping of JSDToStrMode -> JS_dtoa mode */ private static final int dtoaModes[] = { 0, /* DTOSTR_STANDARD */ 0, /* DTOSTR_STANDARD_EXPONENTIAL, */ 3, /* DTOSTR_FIXED, */ 2, /* DTOSTR_EXPONENTIAL, */ 2}; /* DTOSTR_PRECISION */ static void JS_dtostr(StringBuffer buffer, int mode, int precision, double d) { int decPt; /* Position of decimal point relative to first digit returned by JS_dtoa */ boolean[] sign = new boolean[1]; /* true if the sign bit was set in d */ int nDigits; /* Number of significand digits returned by JS_dtoa */// JS_ASSERT(bufferSize >= (size_t)(mode <= DTOSTR_STANDARD_EXPONENTIAL ? DTOSTR_STANDARD_BUFFER_SIZE :// DTOSTR_VARIABLE_BUFFER_SIZE(precision))); if (mode == DTOSTR_FIXED && (d >= 1e21 || d <= -1e21)) mode = DTOSTR_STANDARD; /* Change mode here rather than below because the buffer may not be large enough to hold a large integer. */ decPt = JS_dtoa(d, dtoaModes[mode], mode >= DTOSTR_FIXED, precision, sign, buffer); nDigits = buffer.length(); /* If Infinity, -Infinity, or NaN, return the string regardless of the mode. */ if (decPt != 9999) { boolean exponentialNotation = false; int minNDigits = 0; /* Minimum number of significand digits required by mode and precision */ int p; int q; switch (mode) { case DTOSTR_STANDARD: if (decPt < -5 || decPt > 21) exponentialNotation = true; else minNDigits = decPt; break; case DTOSTR_FIXED: if (precision >= 0) minNDigits = decPt + precision; else minNDigits = decPt; break; case DTOSTR_EXPONENTIAL:// JS_ASSERT(precision > 0); minNDigits = precision; /* Fall through */ case DTOSTR_STANDARD_EXPONENTIAL: exponentialNotation = true; break; case DTOSTR_PRECISION:// JS_ASSERT(precision > 0); minNDigits = precision; if (decPt < -5 || decPt > precision) exponentialNotation = true; break; } /* If the number has fewer than minNDigits, pad it with zeros at the end */ if (nDigits < minNDigits) { p = minNDigits; nDigits = minNDigits; do { buffer.append('0'); } while (buffer.length() != p); } if (exponentialNotation) { /* Insert a decimal point if more than one significand digit */ if (nDigits != 1) { buffer.insert(1, '.'); } buffer.append('e'); if ((decPt - 1) >= 0) buffer.append('+'); buffer.append(decPt - 1);// JS_snprintf(numEnd, bufferSize - (numEnd - buffer), "e%+d", decPt-1); } else if (decPt != nDigits) { /* Some kind of a fraction in fixed notation */// JS_ASSERT(decPt <= nDigits); if (decPt > 0) { /* dd...dd . dd...dd */ buffer.insert(decPt, '.'); } else { /* 0 . 00...00dd...dd */ for (int i = 0; i < 1 - decPt; i++) buffer.insert(0, '0'); buffer.insert(1, '.'); } } } /* If negative and neither -0.0 nor NaN, output a leading '-'. */ if (sign[0] && !(word0(d) == Sign_bit && word1(d) == 0) && !((word0(d) & Exp_mask) == Exp_mask && ((word1(d) != 0) || ((word0(d) & Frac_mask) != 0)))) { buffer.insert(0, '-'); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -