...
Run Format

Source file src/math/big/ftoa.go

     1	// Copyright 2015 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	// This file implements Float-to-string conversion functions.
     6	// It is closely following the corresponding implementation
     7	// in strconv/ftoa.go, but modified and simplified for Float.
     8	
     9	package big
    10	
    11	import (
    12		"bytes"
    13		"fmt"
    14		"strconv"
    15	)
    16	
    17	// Text converts the floating-point number x to a string according
    18	// to the given format and precision prec. The format is one of:
    19	//
    20	//	'e'	-d.dddde±dd, decimal exponent, at least two (possibly 0) exponent digits
    21	//	'E'	-d.ddddE±dd, decimal exponent, at least two (possibly 0) exponent digits
    22	//	'f'	-ddddd.dddd, no exponent
    23	//	'g'	like 'e' for large exponents, like 'f' otherwise
    24	//	'G'	like 'E' for large exponents, like 'f' otherwise
    25	//	'b'	-ddddddp±dd, binary exponent
    26	//	'p'	-0x.dddp±dd, binary exponent, hexadecimal mantissa
    27	//
    28	// For the binary exponent formats, the mantissa is printed in normalized form:
    29	//
    30	//	'b'	decimal integer mantissa using x.Prec() bits, or -0
    31	//	'p'	hexadecimal fraction with 0.5 <= 0.mantissa < 1.0, or -0
    32	//
    33	// If format is a different character, Text returns a "%" followed by the
    34	// unrecognized format character.
    35	//
    36	// The precision prec controls the number of digits (excluding the exponent)
    37	// printed by the 'e', 'E', 'f', 'g', and 'G' formats. For 'e', 'E', and 'f'
    38	// it is the number of digits after the decimal point. For 'g' and 'G' it is
    39	// the total number of digits. A negative precision selects the smallest
    40	// number of decimal digits necessary to identify the value x uniquely using
    41	// x.Prec() mantissa bits.
    42	// The prec value is ignored for the 'b' or 'p' format.
    43	func (x *Float) Text(format byte, prec int) string {
    44		cap := 10 // TODO(gri) determine a good/better value here
    45		if prec > 0 {
    46			cap += prec
    47		}
    48		return string(x.Append(make([]byte, 0, cap), format, prec))
    49	}
    50	
    51	// String formats x like x.Text('g', 10).
    52	// (String must be called explicitly, Float.Format does not support %s verb.)
    53	func (x *Float) String() string {
    54		return x.Text('g', 10)
    55	}
    56	
    57	// Append appends to buf the string form of the floating-point number x,
    58	// as generated by x.Text, and returns the extended buffer.
    59	func (x *Float) Append(buf []byte, fmt byte, prec int) []byte {
    60		// sign
    61		if x.neg {
    62			buf = append(buf, '-')
    63		}
    64	
    65		// Inf
    66		if x.form == inf {
    67			if !x.neg {
    68				buf = append(buf, '+')
    69			}
    70			return append(buf, "Inf"...)
    71		}
    72	
    73		// pick off easy formats
    74		switch fmt {
    75		case 'b':
    76			return x.fmtB(buf)
    77		case 'p':
    78			return x.fmtP(buf)
    79		}
    80	
    81		// Algorithm:
    82		//   1) convert Float to multiprecision decimal
    83		//   2) round to desired precision
    84		//   3) read digits out and format
    85	
    86		// 1) convert Float to multiprecision decimal
    87		var d decimal // == 0.0
    88		if x.form == finite {
    89			// x != 0
    90			d.init(x.mant, int(x.exp)-x.mant.bitLen())
    91		}
    92	
    93		// 2) round to desired precision
    94		shortest := false
    95		if prec < 0 {
    96			shortest = true
    97			roundShortest(&d, x)
    98			// Precision for shortest representation mode.
    99			switch fmt {
   100			case 'e', 'E':
   101				prec = len(d.mant) - 1
   102			case 'f':
   103				prec = max(len(d.mant)-d.exp, 0)
   104			case 'g', 'G':
   105				prec = len(d.mant)
   106			}
   107		} else {
   108			// round appropriately
   109			switch fmt {
   110			case 'e', 'E':
   111				// one digit before and number of digits after decimal point
   112				d.round(1 + prec)
   113			case 'f':
   114				// number of digits before and after decimal point
   115				d.round(d.exp + prec)
   116			case 'g', 'G':
   117				if prec == 0 {
   118					prec = 1
   119				}
   120				d.round(prec)
   121			}
   122		}
   123	
   124		// 3) read digits out and format
   125		switch fmt {
   126		case 'e', 'E':
   127			return fmtE(buf, fmt, prec, d)
   128		case 'f':
   129			return fmtF(buf, prec, d)
   130		case 'g', 'G':
   131			// trim trailing fractional zeros in %e format
   132			eprec := prec
   133			if eprec > len(d.mant) && len(d.mant) >= d.exp {
   134				eprec = len(d.mant)
   135			}
   136			// %e is used if the exponent from the conversion
   137			// is less than -4 or greater than or equal to the precision.
   138			// If precision was the shortest possible, use eprec = 6 for
   139			// this decision.
   140			if shortest {
   141				eprec = 6
   142			}
   143			exp := d.exp - 1
   144			if exp < -4 || exp >= eprec {
   145				if prec > len(d.mant) {
   146					prec = len(d.mant)
   147				}
   148				return fmtE(buf, fmt+'e'-'g', prec-1, d)
   149			}
   150			if prec > d.exp {
   151				prec = len(d.mant)
   152			}
   153			return fmtF(buf, max(prec-d.exp, 0), d)
   154		}
   155	
   156		// unknown format
   157		if x.neg {
   158			buf = buf[:len(buf)-1] // sign was added prematurely - remove it again
   159		}
   160		return append(buf, '%', fmt)
   161	}
   162	
   163	func roundShortest(d *decimal, x *Float) {
   164		// if the mantissa is zero, the number is zero - stop now
   165		if len(d.mant) == 0 {
   166			return
   167		}
   168	
   169		// Approach: All numbers in the interval [x - 1/2ulp, x + 1/2ulp]
   170		// (possibly exclusive) round to x for the given precision of x.
   171		// Compute the lower and upper bound in decimal form and find the
   172		// shortest decimal number d such that lower <= d <= upper.
   173	
   174		// TODO(gri) strconv/ftoa.do describes a shortcut in some cases.
   175		// See if we can use it (in adjusted form) here as well.
   176	
   177		// 1) Compute normalized mantissa mant and exponent exp for x such
   178		// that the lsb of mant corresponds to 1/2 ulp for the precision of
   179		// x (i.e., for mant we want x.prec + 1 bits).
   180		mant := nat(nil).set(x.mant)
   181		exp := int(x.exp) - mant.bitLen()
   182		s := mant.bitLen() - int(x.prec+1)
   183		switch {
   184		case s < 0:
   185			mant = mant.shl(mant, uint(-s))
   186		case s > 0:
   187			mant = mant.shr(mant, uint(+s))
   188		}
   189		exp += s
   190		// x = mant * 2**exp with lsb(mant) == 1/2 ulp of x.prec
   191	
   192		// 2) Compute lower bound by subtracting 1/2 ulp.
   193		var lower decimal
   194		var tmp nat
   195		lower.init(tmp.sub(mant, natOne), exp)
   196	
   197		// 3) Compute upper bound by adding 1/2 ulp.
   198		var upper decimal
   199		upper.init(tmp.add(mant, natOne), exp)
   200	
   201		// The upper and lower bounds are possible outputs only if
   202		// the original mantissa is even, so that ToNearestEven rounding
   203		// would round to the original mantissa and not the neighbors.
   204		inclusive := mant[0]&2 == 0 // test bit 1 since original mantissa was shifted by 1
   205	
   206		// Now we can figure out the minimum number of digits required.
   207		// Walk along until d has distinguished itself from upper and lower.
   208		for i, m := range d.mant {
   209			l := lower.at(i)
   210			u := upper.at(i)
   211	
   212			// Okay to round down (truncate) if lower has a different digit
   213			// or if lower is inclusive and is exactly the result of rounding
   214			// down (i.e., and we have reached the final digit of lower).
   215			okdown := l != m || inclusive && i+1 == len(lower.mant)
   216	
   217			// Okay to round up if upper has a different digit and either upper
   218			// is inclusive or upper is bigger than the result of rounding up.
   219			okup := m != u && (inclusive || m+1 < u || i+1 < len(upper.mant))
   220	
   221			// If it's okay to do either, then round to the nearest one.
   222			// If it's okay to do only one, do it.
   223			switch {
   224			case okdown && okup:
   225				d.round(i + 1)
   226				return
   227			case okdown:
   228				d.roundDown(i + 1)
   229				return
   230			case okup:
   231				d.roundUp(i + 1)
   232				return
   233			}
   234		}
   235	}
   236	
   237	// %e: d.ddddde±dd
   238	func fmtE(buf []byte, fmt byte, prec int, d decimal) []byte {
   239		// first digit
   240		ch := byte('0')
   241		if len(d.mant) > 0 {
   242			ch = d.mant[0]
   243		}
   244		buf = append(buf, ch)
   245	
   246		// .moredigits
   247		if prec > 0 {
   248			buf = append(buf, '.')
   249			i := 1
   250			m := min(len(d.mant), prec+1)
   251			if i < m {
   252				buf = append(buf, d.mant[i:m]...)
   253				i = m
   254			}
   255			for ; i <= prec; i++ {
   256				buf = append(buf, '0')
   257			}
   258		}
   259	
   260		// e±
   261		buf = append(buf, fmt)
   262		var exp int64
   263		if len(d.mant) > 0 {
   264			exp = int64(d.exp) - 1 // -1 because first digit was printed before '.'
   265		}
   266		if exp < 0 {
   267			ch = '-'
   268			exp = -exp
   269		} else {
   270			ch = '+'
   271		}
   272		buf = append(buf, ch)
   273	
   274		// dd...d
   275		if exp < 10 {
   276			buf = append(buf, '0') // at least 2 exponent digits
   277		}
   278		return strconv.AppendInt(buf, exp, 10)
   279	}
   280	
   281	// %f: ddddddd.ddddd
   282	func fmtF(buf []byte, prec int, d decimal) []byte {
   283		// integer, padded with zeros as needed
   284		if d.exp > 0 {
   285			m := min(len(d.mant), d.exp)
   286			buf = append(buf, d.mant[:m]...)
   287			for ; m < d.exp; m++ {
   288				buf = append(buf, '0')
   289			}
   290		} else {
   291			buf = append(buf, '0')
   292		}
   293	
   294		// fraction
   295		if prec > 0 {
   296			buf = append(buf, '.')
   297			for i := 0; i < prec; i++ {
   298				buf = append(buf, d.at(d.exp+i))
   299			}
   300		}
   301	
   302		return buf
   303	}
   304	
   305	// fmtB appends the string of x in the format mantissa "p" exponent
   306	// with a decimal mantissa and a binary exponent, or 0" if x is zero,
   307	// and returns the extended buffer.
   308	// The mantissa is normalized such that is uses x.Prec() bits in binary
   309	// representation.
   310	// The sign of x is ignored, and x must not be an Inf.
   311	func (x *Float) fmtB(buf []byte) []byte {
   312		if x.form == zero {
   313			return append(buf, '0')
   314		}
   315	
   316		if debugFloat && x.form != finite {
   317			panic("non-finite float")
   318		}
   319		// x != 0
   320	
   321		// adjust mantissa to use exactly x.prec bits
   322		m := x.mant
   323		switch w := uint32(len(x.mant)) * _W; {
   324		case w < x.prec:
   325			m = nat(nil).shl(m, uint(x.prec-w))
   326		case w > x.prec:
   327			m = nat(nil).shr(m, uint(w-x.prec))
   328		}
   329	
   330		buf = append(buf, m.utoa(10)...)
   331		buf = append(buf, 'p')
   332		e := int64(x.exp) - int64(x.prec)
   333		if e >= 0 {
   334			buf = append(buf, '+')
   335		}
   336		return strconv.AppendInt(buf, e, 10)
   337	}
   338	
   339	// fmtP appends the string of x in the format "0x." mantissa "p" exponent
   340	// with a hexadecimal mantissa and a binary exponent, or "0" if x is zero,
   341	// and returns the extended buffer.
   342	// The mantissa is normalized such that 0.5 <= 0.mantissa < 1.0.
   343	// The sign of x is ignored, and x must not be an Inf.
   344	func (x *Float) fmtP(buf []byte) []byte {
   345		if x.form == zero {
   346			return append(buf, '0')
   347		}
   348	
   349		if debugFloat && x.form != finite {
   350			panic("non-finite float")
   351		}
   352		// x != 0
   353	
   354		// remove trailing 0 words early
   355		// (no need to convert to hex 0's and trim later)
   356		m := x.mant
   357		i := 0
   358		for i < len(m) && m[i] == 0 {
   359			i++
   360		}
   361		m = m[i:]
   362	
   363		buf = append(buf, "0x."...)
   364		buf = append(buf, bytes.TrimRight(m.utoa(16), "0")...)
   365		buf = append(buf, 'p')
   366		if x.exp >= 0 {
   367			buf = append(buf, '+')
   368		}
   369		return strconv.AppendInt(buf, int64(x.exp), 10)
   370	}
   371	
   372	func min(x, y int) int {
   373		if x < y {
   374			return x
   375		}
   376		return y
   377	}
   378	
   379	var _ fmt.Formatter = &floatZero // *Float must implement fmt.Formatter
   380	
   381	// Format implements fmt.Formatter. It accepts all the regular
   382	// formats for floating-point numbers ('b', 'e', 'E', 'f', 'F',
   383	// 'g', 'G') as well as 'p' and 'v'. See (*Float).Text for the
   384	// interpretation of 'p'. The 'v' format is handled like 'g'.
   385	// Format also supports specification of the minimum precision
   386	// in digits, the output field width, as well as the format flags
   387	// '+' and ' ' for sign control, '0' for space or zero padding,
   388	// and '-' for left or right justification. See the fmt package
   389	// for details.
   390	func (x *Float) Format(s fmt.State, format rune) {
   391		prec, hasPrec := s.Precision()
   392		if !hasPrec {
   393			prec = 6 // default precision for 'e', 'f'
   394		}
   395	
   396		switch format {
   397		case 'e', 'E', 'f', 'b', 'p':
   398			// nothing to do
   399		case 'F':
   400			// (*Float).Text doesn't support 'F'; handle like 'f'
   401			format = 'f'
   402		case 'v':
   403			// handle like 'g'
   404			format = 'g'
   405			fallthrough
   406		case 'g', 'G':
   407			if !hasPrec {
   408				prec = -1 // default precision for 'g', 'G'
   409			}
   410		default:
   411			fmt.Fprintf(s, "%%!%c(*big.Float=%s)", format, x.String())
   412			return
   413		}
   414		var buf []byte
   415		buf = x.Append(buf, byte(format), prec)
   416		if len(buf) == 0 {
   417			buf = []byte("?") // should never happen, but don't crash
   418		}
   419		// len(buf) > 0
   420	
   421		var sign string
   422		switch {
   423		case buf[0] == '-':
   424			sign = "-"
   425			buf = buf[1:]
   426		case buf[0] == '+':
   427			// +Inf
   428			sign = "+"
   429			if s.Flag(' ') {
   430				sign = " "
   431			}
   432			buf = buf[1:]
   433		case s.Flag('+'):
   434			sign = "+"
   435		case s.Flag(' '):
   436			sign = " "
   437		}
   438	
   439		var padding int
   440		if width, hasWidth := s.Width(); hasWidth && width > len(sign)+len(buf) {
   441			padding = width - len(sign) - len(buf)
   442		}
   443	
   444		switch {
   445		case s.Flag('0') && !x.IsInf():
   446			// 0-padding on left
   447			writeMultiple(s, sign, 1)
   448			writeMultiple(s, "0", padding)
   449			s.Write(buf)
   450		case s.Flag('-'):
   451			// padding on right
   452			writeMultiple(s, sign, 1)
   453			s.Write(buf)
   454			writeMultiple(s, " ", padding)
   455		default:
   456			// padding on left
   457			writeMultiple(s, " ", padding)
   458			writeMultiple(s, sign, 1)
   459			s.Write(buf)
   460		}
   461	}
   462	

View as plain text