package ftoaimport ()const ( exp_11 = 0x3ff00000 frac_mask1 = 0xfffff bletch = 0x10 quick_max = 14 int_max = 14)var ( tens = [...]float64{1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,1e20, 1e21, 1e22, } bigtens = [...]float64{1e16, 1e32, 1e64, 1e128, 1e256} big5 = big.NewInt(5) big10 = big.NewInt(10) p05 = []*big.Int{big5, big.NewInt(25), big.NewInt(125)} pow5Cache [7]*big.Int dtoaModes = []int{ModeStandard: 0,ModeStandardExponential: 0,ModeFixed: 3,ModeExponential: 2,ModePrecision: 2, })/*d must be > 0 and must not be Infmode: 0 ==> shortest string that yields d when read in and rounded to nearest. 1 ==> like 0, but with Steele & White stopping rule; e.g. with IEEE P754 arithmetic , mode 0 gives 1e23 whereas mode 1 gives 9.999999999999999e22. 2 ==> max(1,ndigits) significant digits. This gives a return value similar to that of ecvt, except that trailing zeros are suppressed. 3 ==> through ndigits past the decimal point. This gives a return value similar to that from fcvt, except that trailing zeros are suppressed, and ndigits can be negative. 4,5 ==> similar to 2 and 3, respectively, but (in round-nearest mode) with the tests of mode 0 to possibly return a shorter string that rounds to d. With IEEE arithmetic and compilation with -DHonor_FLT_ROUNDS, modes 4 and 5 behave the same as modes 2 and 3 when FLT_ROUNDS != 1. 6-9 ==> Debugging modes similar to mode - 4: don't try fast floating-point estimate (if applicable). Values of mode other than 0-9 are treated as mode 0.*/func ftoa( float64, int, bool, int, []byte) ([]byte, int) { := len() := make([]byte, 0, 8) , , := d2b(, ) := math.Float64bits() := uint32( >> 32) := uint32() := int(( >> exp_shift1) & (exp_mask >> exp_shift1))varfloat64varboolif != 0 { = setWord0(, (&frac_mask1)|exp_11) -= bias = false } else {/* d is denormalized */ = + + (bias + (p - 1) - 1)varuint64if > 32 { = uint64()<<(64-) | uint64()>>(-32) } else { = uint64() << (32 - ) } = setWord0(float64(), uint32((>>32)-31*exp_mask)) -= (bias + (p - 1) - 1) + 1 = true }/* At this point d = f*2^i, where 1 <= f < 2. d2 is an approximation of f. */ := (-1.5)*0.289529654602168 + 0.1760912590558 + float64()*0.301029995663981 := int()if < 0.0 && != float64() { -- /* want k = floor(ds) */ } := trueif >= 0 && < len(tens) {if < tens[] { -- } = false }/* At this point floor(log10(d)) <= k <= floor(log10(d))+1. If k_check is zero, we're guaranteed that k = floor(log10(d)). */ := - - 1var , , , int/* At this point d = b/2^j, where b is an odd integer. */if >= 0 { = 0 = } else { = - = 0 }if >= 0 { = 0 = += } else { -= = - = 0 }/* At this point d/10^k = (b * 2^b2 * 5^b5) / (2^s2 * 5^s5), where b is an odd integer, b2 >= 0, b5 >= 0, s2 >= 0, and s5 >= 0. */if < 0 || > 9 { = 0 } := trueif > 5 { -= 4 = false } := truevar , intswitch {case0, 1: , = -1, -1 = 0case2: = falsefallthroughcase4:if <= 0 { = 1 } , = , case3: = falsefallthroughcase5: = + + 1 = = - 1 }/* ilim is the maximum number of significant digits we want, based on k and ndigits. */ /* ilim1 is the maximum number of significant digits we want, based on k and ndigits, when it turns out that k was computed too high by one. */ := falseif >= 0 && <= quick_max && {/* Try to get by with floating-point arithmetic. */ = 0 = := := := 2/* conservative *//* Divide d by 10^k, keeping track of the roundoff error and avoiding overflows. */if > 0 { = tens[&0xf] = >> 4if ( & bletch) != 0 {/* prevent overflows */ &= bletch - 1 /= bigtens[len(bigtens)-1] ++ }for ; != 0; ++ {if ( & 1) != 0 { ++ *= bigtens[] } >>= 1 } /= } elseif := -; != 0 { *= tens[&0xf]for = >> 4; != 0; ++ {if ( & 1) != 0 { ++ *= bigtens[] } >>= 1 } }/* Check that k was computed correctly. */if && < 1.0 && > 0 {if <= 0 { = true } else { = -- *= 10. ++ } }/* eps bounds the cumulative error. */ := float64()* + 7.0 = setWord0(, _word0()-(p-1)*exp_msk1)if == 0 { -= 5.0if > { = append(, '1') ++return , + 1 }if < - { = append(, '0')return , 1 } = true }if ! { = trueif {/* Use Steele & White method of only * generating digits needed. */ = 0.5/tens[-1] - for = 0; ; { := int64() -= float64() = append(, byte('0'+))if < {return , + 1 }if1.0- < { , = bumpUp(, )return , + 1 } ++if >= {break } *= 10.0 *= 10.0 } } else {/* Generate ilim digits, then fix them up. */ *= tens[-1]for = 1; ; ++ { := int64() -= float64() = append(, byte('0'+))if == {if > 0.5+ { , = bumpUp(, )return , + 1 } elseif < 0.5- { = stripTrailingZeroes(, )return , + 1 }break } *= 10.0 } } }if { = [:] = = = } }/* Do we have a "small" integer? */if >= 0 && <= int_max {/* Yes. */ = tens[]if < 0 && <= 0 {if < 0 || < 5* || (! && == 5*) { = [:] = append(, '0')return , 1 } = append(, '1') ++return , + 1 }for = 1; ; ++ { := int64( / ) -= float64() * = append(, byte('0'+))if == { += if ( > ) || ( == && ((( & 1) != 0) || )) { , = bumpUp(, ) }break } *= 10.0if == 0 {break } }return , + 1 } := := var , *big.Intif {if < 2 {if { = + (bias + (p - 1) - 1 + 1) } else { = 1 + p - }/* 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 { = - 1if >= { -= } else { -= += += = 0 } = if < 0 { -= = 0 }/* (2^m2 * 5^m5) / (2^(s2+i) * 5^s5) = (1/2 * 10^(1-ilim))/10^k. */ } += += = big.NewInt(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 > 0 && > 0 {if < { = } else { = } -= -= -= } := new(big.Int).SetBytes()/* Fold b5 into b and m5 into mhi. */if > 0 {if {if > 0 {pow5mult(, ) .Mul(, ) } = - if != 0 {pow5mult(, ) } } else {pow5mult(, ) } }/* 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. */ := big.NewInt(1)if > 0 {pow5mult(, ) }/* 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. */ := falseif < 2 {if (_word1() == 0) && ((_word0() & bndry_mask) == 0) && ((_word0() & (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. */ += log2P += log2P = 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. */varintif != 0 { := .Bytes()varuint32for := 0; < 4; ++ { = << 8if < len() { |= uint32([]) } } = 32 - hi0bits() } else { = 1 } = ( + ) & 0x1fif != 0 { = 32 - }/* i is the number of leading zero bits in the most significant word of S*2^s2. */if > 4 { -= 4 += += += } elseif < 4 { += 28 += += += }/* Now S*2^s2 has exactly four leading zero bits in its most significant word. */if > 0 { = .Lsh(, uint()) }if > 0 { .Lsh(, uint()) }/* Now we have d/10^k = b/S and (mhi * 2^m2) / S = maximum acceptable error, divided by 10^k. */if {if .Cmp() < 0 { -- .Mul(, big10) /* we botched the k estimate */if { .Mul(, big10) } = } }/* At this point 1 <= d/10^k = b/S < 10. */if <= 0 && > 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 >= 0 { = .Cmp(.Mul(, big5)) }if < 0 || < 0 || == 0 && ! {/* 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. */ = [:] = append(, '0')return , 1 } = append(, '1') ++return , + 1 }varbyteif {if > 0 { .Lsh(, uint()) }/* Compute mlo -- check for special case * that d is a normalized power of 2. */ = if { = = new(big.Int).Lsh(, 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. */var , big.Intfor = 1; ; ++ { .DivMod(, , ) = byte(.Int64() + '0')/* Do we yet have the shortest decimal string * that will round to d? */ = .Cmp()/* j is b/S compared with mlo/S. */ .Sub(, )varintif .Sign() <= 0 { = 1 } else { = .Cmp(&) }/* j1 is b/S compared with 1 - mhi/S. */if ( == 0) && ( == 0) && ((_word1() & 1) == 0) {if == '9' {varbool = append(, '9')if , = roundOff(, ); { ++ = append(, '1') }return , + 1 }if > 0 { ++ } = append(, )return , + 1 }if ( < 0) || (( == 0) && ( == 0) && ((_word1() & 1) == 0)) {if > 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. */ .Lsh(, 1) = .Cmp()if ( > 0) || ( == 0 && ((( & 1) == 1) || )) { ++if == '9' { = append(, '9') , := roundOff(, )if { ++ = append(, '1') }return , + 1 } } } = append(, )return , + 1 }if > 0 {if == '9' { /* possible if i == 1 */ = append(, '9') , := roundOff(, )if { ++ = append(, '1') }return , + 1 } = append(, +1)return , + 1 } = append(, )if == {break } .Mul(, big10)if == { .Mul(, big10) } else { .Mul(, big10) .Mul(, big10) } } } else {varbig.Intfor = 1; ; ++ { .DivMod(, , ) = byte(.Int64() + '0') = append(, )if >= {break } .Mul(, big10) } }/* Round off last digit */ .Lsh(, 1) = .Cmp()if ( > 0) || ( == 0 && ((( & 1) == 1) || )) {varbool , = roundOff(, )if { ++ = append(, '1')return , + 1 } } else { = stripTrailingZeroes(, ) }return , + 1}func bumpUp( []byte, int) ([]byte, int) {varbyte := 0iflen() > 0 && [0] == '-' { = 1 }for { = [len()-1] = [:len()-1]if != '9' {break }iflen() == { ++ = '0'break } } = append(, +1)return , }func setWord0( float64, uint32) float64 { := math.Float64bits()returnmath.Float64frombits(uint64()<<32 | &0xffffffff)}func _word0( float64) uint32 { := math.Float64bits()returnuint32( >> 32)}func _word1( float64) uint32 { := math.Float64bits()returnuint32()}func stripTrailingZeroes( []byte, int) []byte { := len() - 1for >= && [] == '0' { -- }return [:+1]}/* Set b = b * 5^k. k must be nonnegative. */func pow5mult( *big.Int, int) *big.Int {if < (1 << (len(pow5Cache) + 2)) { := & 3if != 0 { .Mul(, p05[-1]) } >>= 2 = 0for {if &1 != 0 { .Mul(, pow5Cache[]) } >>= 1if == 0 {break } ++ }return }return .Mul(, new(big.Int).Exp(big5, big.NewInt(int64()), nil))}func roundOff( []byte, int) ([]byte, bool) { := len()for != { --if [] != '9' { []++return [:+1], false } }return [:], true}func init() { := big.NewInt(625)pow5Cache[0] = for := 1; < len(pow5Cache); ++ { = new(big.Int).Mul(, )pow5Cache[] = }}
The pages are generated with Goldsv0.8.2. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.