📄 dtoa.java
字号:
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 { stripTrailingZeroes(buf);// 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; } private static void stripTrailingZeroes(StringBuffer buf) {// while(*--s == '0') ;// s++; int bl = buf.length(); while(bl-->0 && buf.charAt(bl) == '0'); buf.setLength(bl + 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 + -