// Copyright 2021 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.package strconvimport ()// binary to decimal conversion using the Ryū algorithm.//// See Ulf Adams, "Ryū: Fast Float-to-String Conversion" (doi:10.1145/3192366.3192369)//// Fixed precision formatting is a variant of the original paper's// algorithm, where a single multiplication by 10^k is required,// sharing the same rounding guarantees.// ryuFtoaFixed32 formats mant*(2^exp) with prec decimal digits.func ( *decimalSlice, uint32, int, int) {if < 0 {panic("ryuFtoaFixed32 called with negative prec") }if > 9 {panic("ryuFtoaFixed32 called with prec > 9") }// Zero input.if == 0 { .nd, .dp = 0, 0return }// Renormalize to a 25-bit mantissa. := if := bits.Len32(); < 25 { <<= uint(25 - ) += - 25 }// Choose an exponent such that rounded mant*(2^e2)*(10^q) has // at least prec decimal digits, i.e // mant*(2^e2)*(10^q) >= 10^(prec-1) // Because mant >= 2^24, it is enough to choose: // 2^(e2+24) >= 10^(-q+prec-1) // or q = -mulByLog2Log10(e2+24) + prec - 1 := -mulByLog2Log10(+24) + - 1// Now compute mant*(2^e2)*(10^q). // Is it an exact computation? // Only small positive powers of 10 are exact (5^28 has 66 bits). := <= 27 && >= 0 , , := mult64bitPow10(, , )if >= 0 {panic("not enough significant bits after mult64bitPow10") }// As a special case, computation might still be exact, if exponent // was negative and if it amounts to computing an exact division. // In that case, we ignore all lower bits. // Note that division by 10^11 cannot be exact as 5^11 has 26 bits.if < 0 && >= -10 && divisibleByPower5(uint64(), -) { = true = true }// Remove extra lower bits and keep rounding info. := uint(-) := uint32(1<< - 1) , := >>, & := falseif {// If we computed an exact product, d + 1/2 // should round to d+1 if 'd' is odd. = > 1<<(-1) || ( == 1<<(-1) && !) || ( == 1<<(-1) && && &1 == 1) } else {// otherwise, d+1/2 always rounds up because // we truncated below. = >>(-1) == 1 }if != 0 { = false }// Proceed to the requested number of digitsformatDecimal(, uint64(), !, , )// Adjust exponent .dp -= }// ryuFtoaFixed64 formats mant*(2^exp) with prec decimal digits.func ( *decimalSlice, uint64, int, int) {if > 18 {panic("ryuFtoaFixed64 called with prec > 18") }// Zero input.if == 0 { .nd, .dp = 0, 0return }// Renormalize to a 55-bit mantissa. := if := bits.Len64(); < 55 { = << uint(55-) += - 55 }// Choose an exponent such that rounded mant*(2^e2)*(10^q) has // at least prec decimal digits, i.e // mant*(2^e2)*(10^q) >= 10^(prec-1) // Because mant >= 2^54, it is enough to choose: // 2^(e2+54) >= 10^(-q+prec-1) // or q = -mulByLog2Log10(e2+54) + prec - 1 // // The minimal required exponent is -mulByLog2Log10(1025)+18 = -291 // The maximal required exponent is mulByLog2Log10(1074)+18 = 342 := -mulByLog2Log10(+54) + - 1// Now compute mant*(2^e2)*(10^q). // Is it an exact computation? // Only small positive powers of 10 are exact (5^55 has 128 bits). := <= 55 && >= 0 , , := mult128bitPow10(, , )if >= 0 {panic("not enough significant bits after mult128bitPow10") }// As a special case, computation might still be exact, if exponent // was negative and if it amounts to computing an exact division. // In that case, we ignore all lower bits. // Note that division by 10^23 cannot be exact as 5^23 has 54 bits.if < 0 && >= -22 && divisibleByPower5(, -) { = true = true }// Remove extra lower bits and keep rounding info. := uint(-) := uint64(1<< - 1) , := >>, & := falseif {// If we computed an exact product, d + 1/2 // should round to d+1 if 'd' is odd. = > 1<<(-1) || ( == 1<<(-1) && !) || ( == 1<<(-1) && && &1 == 1) } else {// otherwise, d+1/2 always rounds up because // we truncated below. = >>(-1) == 1 }if != 0 { = false }// Proceed to the requested number of digitsformatDecimal(, , !, , )// Adjust exponent .dp -= }varuint64pow10 = [...]uint64{1, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,}// formatDecimal fills d with at most prec decimal digits// of mantissa m. The boolean trunc indicates whether m// is truncated compared to the original number being formatted.func ( *decimalSlice, uint64, bool, bool, int) { := uint64pow10[] := 0for >= { , := /10, %10 = ++if > 5 { = true } elseif < 5 { = false } else { // b == 5// round up if there are trailing digits, // or if the new value of m is odd (round-to-even convention) = || &1 == 1 }if != 0 { = true } }if { ++ }if >= {// Happens if di was originally 99999....xx /= 10 ++ }// render digits (similar to formatBits) := uint() .nd = := for >= 100 {var , uint64if >>32 == 0 { , = uint64(uint32()/100), uint64(uint32()%100) } else { , = /100, %100 } -= 2 .d[+1] = smallsString[2*+1] .d[+0] = smallsString[2*+0] = }if > 0 { -- .d[] = smallsString[2*+1] }if >= 10 { -- .d[] = smallsString[2*] }for .d[.nd-1] == '0' { .nd-- ++ } .dp = .nd + }// ryuFtoaShortest formats mant*2^exp with prec decimal digits.func ( *decimalSlice, uint64, int, *floatInfo) {if == 0 { .nd, .dp = 0, 0return }// If input is an exact integer with fewer bits than the mantissa, // the previous and next integer are not admissible representations.if <= 0 && bits.TrailingZeros64() >= - { >>= uint(-)ryuDigits(, , , , true, false)return } , , , := computeBounds(, , )if == 0 {ryuDigits(, , , , true, false)return }// Find 10^q *larger* than 2^-e2 := mulByLog2Log10(-) + 1// We are going to multiply by 10^q using 128-bit arithmetic. // The exponent is the same for all 3 numbers.var , , uint64var , , boolif == &float32info {var , , uint32 , _, = mult64bitPow10(uint32(), , ) , _, = mult64bitPow10(uint32(), , ) , , = mult64bitPow10(uint32(), , ) , , = uint64(), uint64(), uint64() } else { , _, = mult128bitPow10(, , ) , _, = mult128bitPow10(, , ) , , = mult128bitPow10(, , ) }if >= 0 {panic("not enough significant bits after mult128bitPow10") }// Is it an exact computation?if > 55 {// Large positive powers of ten are not exact , , = false, false, false }if < 0 && >= -24 {// Division by a power of ten may be exact. // (note that 5^25 is a 59-bit number so division by 5^25 is never exact).ifdivisibleByPower5(, -) { = true }ifdivisibleByPower5(, -) { = true }ifdivisibleByPower5(, -) { = true } }// Express the results (dl, dc, du)*2^e2 as integers. // Extra bits must be removed and rounding hints computed. := uint(-) := uint64(1<< - 1)// Now compute the floored, integral base 10 mantissas. , := >>, & , := >>, & , := >>, &// Is it allowed to use 'du' as a result? // It is always allowed when it is truncated, but also // if it is exact and the original binary mantissa is even // When disallowed, we can subtract 1. := ! || > 0if && == 0 { = &1 == 0 }if ! { -- }// Is 'dc' the correctly rounded base 10 mantissa? // The correct rounding might be dc+1 := false// don't round up.if {// If we computed an exact product, the half integer // should round to next (even) integer if 'dc' is odd. = > 1<<(-1) || ( == 1<<(-1) && &1 == 1) } else {// otherwise, the result is a lower truncation of the ideal // result. = >>(-1) == 1 }// Is 'dl' an allowed representation? // Only if it is an exact value, and if the original binary mantissa // was even. := && == 0 && (&1 == 0)if ! { ++ }// We need to remember whether the trimmed digits of 'dc' are zero. := && == 0// render digitsryuDigits(, , , , , ) .dp -= }// mulByLog2Log10 returns math.Floor(x * log(2)/log(10)) for an integer x in// the range -1600 <= x && x <= +1600.//// The range restriction lets us work in faster integer arithmetic instead of// slower floating point arithmetic. Correctness is verified by unit tests.func ( int) int {// log(2)/log(10) ≈ 0.30102999566 ≈ 78913 / 2^18return ( * 78913) >> 18}// mulByLog10Log2 returns math.Floor(x * log(10)/log(2)) for an integer x in// the range -500 <= x && x <= +500.//// The range restriction lets us work in faster integer arithmetic instead of// slower floating point arithmetic. Correctness is verified by unit tests.func ( int) int {// log(10)/log(2) ≈ 3.32192809489 ≈ 108853 / 2^15return ( * 108853) >> 15}// computeBounds returns a floating-point vector (l, c, u)×2^e2// where the mantissas are 55-bit (or 26-bit) integers, describing the interval// represented by the input float64 or float32.func ( uint64, int, *floatInfo) (, , uint64, int) {if != 1<<.mantbits || == .bias+1-int(.mantbits) {// regular case (or denormals) , , = 2*-1, 2*, 2*+1 = - 1return } else {// border of an exponent , , = 4*-1, 4*, 4*+2 = - 2return }}func ( *decimalSlice, , , uint64, , bool) { , := divmod1e9() , := divmod1e9() , := divmod1e9()if == 0 {// only low digits (for denormals)ryuDigits32(, , , , , , 8) } elseif < {// truncate 9 digits at once.if != 0 { ++ } = && == 0 = ( > 5e8) || ( == 5e8 && )ryuDigits32(, , , , , , 8) .dp += 9 } else { .nd = 0// emit high part := uint(9)for := ; > 0; { , := /10, %10 = -- .d[] = byte( + '0') } .d = .d[:] .nd = int(9 - )// emit low partryuDigits32(, , , , , , .nd+8) }// trim trailing zerosfor .nd > 0 && .d[.nd-1] == '0' { .nd-- }// trim initial zerosfor .nd > 0 && .d[0] == '0' { .nd-- .dp-- .d = .d[1:] }}// ryuDigits32 emits decimal digits for a number less than 1e9.func ( *decimalSlice, , , uint32, , bool, int) {if == 0 { .dp = + 1return } := 0// Remember last trimmed digit to check for round-up. // c0 will be used to remember zeroness of following digits. := 0for > 0 {// Repeatedly compute: // l = Ceil(lower / 10^k) // c = Round(central / 10^k) // u = Floor(upper / 10^k) // and stop when c goes out of the (l, u) interval. := ( + 9) / 10 , := /10, %10 := / 10if > {// don't trim the last digit as it is forbidden to go below l // other, trim and exit now.break }// Check that we didn't cross the lower boundary. // The case where l < u but c == l-1 is essentially impossible, // but may happen if: // lower = ..11 // central = ..19 // upper = ..31 // and means that 'central' is very close but less than // an integer ending with many zeros, and usually // the "round-up" logic hides the problem.if == +1 && < { ++ = 0 = false } ++// Remember trimmed digits of c = && == 0 = int() , , = , , }// should we round up?if > 0 { = > 5 || ( == 5 && !) || ( == 5 && && &1 == 1) }if < && { ++ }// We know where the number ends, fill directly -= := := for > .nd { , := /100, %100 .d[] = smallsString[2*+1] .d[-1] = smallsString[2*+0] -= 2 = }if == .nd { .d[] = byte( + '0') } .nd = + 1 .dp = .nd + }// mult64bitPow10 takes a floating-point input with a 25-bit// mantissa and multiplies it with 10^q. The resulting mantissa// is m*P >> 57 where P is a 64-bit element of the detailedPowersOfTen tables.// It is typically 31 or 32-bit wide.// The returned boolean is true if all trimmed bits were zero.//// That is://// m*2^e2 * round(10^q) = resM * 2^resE + ε// exact = ε == 0func ( uint32, , int) ( uint32, int, bool) {if == 0 {// P == 1<<63return << 6, - 6, true }if < detailedPowersOfTenMinExp10 || detailedPowersOfTenMaxExp10 < {// This never happens due to the range of float32/float64 exponentpanic("mult64bitPow10: power of 10 is out of range") } := detailedPowersOfTen[-detailedPowersOfTenMinExp10][1]if < 0 {// Inverse powers of ten must be rounded up. += 1 } , := bits.Mul64(uint64(), ) += mulByLog10Log2() - 63 + 57returnuint32(<<7 | >>57), , <<7 == 0}// mult128bitPow10 takes a floating-point input with a 55-bit// mantissa and multiplies it with 10^q. The resulting mantissa// is m*P >> 119 where P is a 128-bit element of the detailedPowersOfTen tables.// It is typically 63 or 64-bit wide.// The returned boolean is true is all trimmed bits were zero.//// That is://// m*2^e2 * round(10^q) = resM * 2^resE + ε// exact = ε == 0func ( uint64, , int) ( uint64, int, bool) {if == 0 {// P == 1<<127return << 8, - 8, true }if < detailedPowersOfTenMinExp10 || detailedPowersOfTenMaxExp10 < {// This never happens due to the range of float32/float64 exponentpanic("mult128bitPow10: power of 10 is out of range") } := detailedPowersOfTen[-detailedPowersOfTenMinExp10]if < 0 {// Inverse powers of ten must be rounded up. [0] += 1 } += mulByLog10Log2() - 127 + 119// long multiplication , := bits.Mul64(, [0]) , := bits.Mul64(, [1]) , := bits.Add64(, , 0) += return <<9 | >>55, , <<9 == 0 && == 0}func ( uint64, int) bool {if == 0 {returntrue }for := 0; < ; ++ {if %5 != 0 {returnfalse } /= 5 }returntrue}// divmod1e9 computes quotient and remainder of division by 1e9,// avoiding runtime uint64 division on 32-bit platforms.func ( uint64) (uint32, uint32) {if !host32bit {returnuint32( / 1e9), uint32( % 1e9) }// Use the same sequence of operations as the amd64 compiler. , := bits.Mul64(>>1, 0x89705f4136b4a598) // binary digits of 1e-9 := >> 28returnuint32(), uint32( - *1e9)}
The pages are generated with Goldsv0.6.7. (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 @Go100and1 (reachable from the left QR code) to get the latest news of Golds.