github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/math/big/ratconv.go (about) 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 rat-to-string conversion functions. 6 7 package big 8 9 import ( 10 "errors" 11 "fmt" 12 "io" 13 "strconv" 14 "strings" 15 ) 16 17 func ratTok(ch rune) bool { 18 return strings.ContainsRune("+-/0123456789.eE", ch) 19 } 20 21 var ratZero Rat 22 var _ fmt.Scanner = &ratZero // *Rat must implement fmt.Scanner 23 24 // Scan is a support routine for fmt.Scanner. It accepts the formats 25 // 'e', 'E', 'f', 'F', 'g', 'G', and 'v'. All formats are equivalent. 26 func (z *Rat) Scan(s fmt.ScanState, ch rune) error { 27 tok, err := s.Token(true, ratTok) 28 if err != nil { 29 return err 30 } 31 if !strings.ContainsRune("efgEFGv", ch) { 32 return errors.New("Rat.Scan: invalid verb") 33 } 34 if _, ok := z.SetString(string(tok)); !ok { 35 return errors.New("Rat.Scan: invalid syntax") 36 } 37 return nil 38 } 39 40 // SetString sets z to the value of s and returns z and a boolean indicating 41 // success. s can be given as a fraction "a/b" or as a decimal floating-point 42 // number optionally followed by an exponent. The entire string (not just a prefix) 43 // must be valid for success. If the operation failed, the value of z is 44 // undefined but the returned value is nil. 45 func (z *Rat) SetString(s string) (*Rat, bool) { 46 if len(s) == 0 { 47 return nil, false 48 } 49 // len(s) > 0 50 51 // parse fraction a/b, if any 52 if sep := strings.Index(s, "/"); sep >= 0 { 53 if _, ok := z.a.SetString(s[:sep], 0); !ok { 54 return nil, false 55 } 56 r := strings.NewReader(s[sep+1:]) 57 var err error 58 if z.b.abs, _, _, err = z.b.abs.scan(r, 0, false); err != nil { 59 return nil, false 60 } 61 // entire string must have been consumed 62 if _, err = r.ReadByte(); err != io.EOF { 63 return nil, false 64 } 65 if len(z.b.abs) == 0 { 66 return nil, false 67 } 68 return z.norm(), true 69 } 70 71 // parse floating-point number 72 r := strings.NewReader(s) 73 74 // sign 75 neg, err := scanSign(r) 76 if err != nil { 77 return nil, false 78 } 79 80 // mantissa 81 // TODO(gri) allow other bases besides 10 for mantissa and exponent? (issue #29799) 82 var ecorr int 83 z.a.abs, _, ecorr, err = z.a.abs.scan(r, 10, true) 84 if err != nil { 85 return nil, false 86 } 87 88 // exponent 89 var exp int64 90 exp, _, err = scanExponent(r, false) 91 if err != nil { 92 return nil, false 93 } 94 95 // there should be no unread characters left 96 if _, err = r.ReadByte(); err != io.EOF { 97 return nil, false 98 } 99 100 // special-case 0 (see also issue #16176) 101 if len(z.a.abs) == 0 { 102 return z, true 103 } 104 // len(z.a.abs) > 0 105 106 // correct exponent 107 if ecorr < 0 { 108 exp += int64(ecorr) 109 } 110 111 // compute exponent power 112 expabs := exp 113 if expabs < 0 { 114 expabs = -expabs 115 } 116 powTen := nat(nil).expNN(natTen, nat(nil).setWord(Word(expabs)), nil) 117 118 // complete fraction 119 if exp < 0 { 120 z.b.abs = powTen 121 z.norm() 122 } else { 123 z.a.abs = z.a.abs.mul(z.a.abs, powTen) 124 z.b.abs = z.b.abs[:0] 125 } 126 127 z.a.neg = neg && len(z.a.abs) > 0 // 0 has no sign 128 129 return z, true 130 } 131 132 // scanExponent scans the longest possible prefix of r representing a decimal 133 // ('e', 'E') or binary ('p') exponent, if any. It returns the exponent, the 134 // exponent base (10 or 2), or a read or syntax error, if any. 135 // 136 // exponent = ( "E" | "e" | "p" ) [ sign ] digits . 137 // sign = "+" | "-" . 138 // digits = digit { digit } . 139 // digit = "0" ... "9" . 140 // 141 // A binary exponent is only permitted if binExpOk is set. 142 func scanExponent(r io.ByteScanner, binExpOk bool) (exp int64, base int, err error) { 143 base = 10 144 145 var ch byte 146 if ch, err = r.ReadByte(); err != nil { 147 if err == io.EOF { 148 err = nil // no exponent; same as e0 149 } 150 return 151 } 152 153 switch ch { 154 case 'e', 'E': 155 // ok 156 case 'p': 157 if binExpOk { 158 base = 2 159 break // ok 160 } 161 fallthrough // binary exponent not permitted 162 default: 163 r.UnreadByte() 164 return // no exponent; same as e0 165 } 166 167 var neg bool 168 if neg, err = scanSign(r); err != nil { 169 return 170 } 171 172 var digits []byte 173 if neg { 174 digits = append(digits, '-') 175 } 176 177 // no need to use nat.scan for exponent digits 178 // since we only care about int64 values - the 179 // from-scratch scan is easy enough and faster 180 for i := 0; ; i++ { 181 if ch, err = r.ReadByte(); err != nil { 182 if err != io.EOF || i == 0 { 183 return 184 } 185 err = nil 186 break // i > 0 187 } 188 if ch < '0' || '9' < ch { 189 if i == 0 { 190 r.UnreadByte() 191 err = fmt.Errorf("invalid exponent (missing digits)") 192 return 193 } 194 break // i > 0 195 } 196 digits = append(digits, ch) 197 } 198 // i > 0 => we have at least one digit 199 200 exp, err = strconv.ParseInt(string(digits), 10, 64) 201 return 202 } 203 204 // String returns a string representation of x in the form "a/b" (even if b == 1). 205 func (x *Rat) String() string { 206 return string(x.marshal()) 207 } 208 209 // marshal implements String returning a slice of bytes 210 func (x *Rat) marshal() []byte { 211 var buf []byte 212 buf = x.a.Append(buf, 10) 213 buf = append(buf, '/') 214 if len(x.b.abs) != 0 { 215 buf = x.b.Append(buf, 10) 216 } else { 217 buf = append(buf, '1') 218 } 219 return buf 220 } 221 222 // RatString returns a string representation of x in the form "a/b" if b != 1, 223 // and in the form "a" if b == 1. 224 func (x *Rat) RatString() string { 225 if x.IsInt() { 226 return x.a.String() 227 } 228 return x.String() 229 } 230 231 // FloatString returns a string representation of x in decimal form with prec 232 // digits of precision after the decimal point. The last digit is rounded to 233 // nearest, with halves rounded away from zero. 234 func (x *Rat) FloatString(prec int) string { 235 var buf []byte 236 237 if x.IsInt() { 238 buf = x.a.Append(buf, 10) 239 if prec > 0 { 240 buf = append(buf, '.') 241 for i := prec; i > 0; i-- { 242 buf = append(buf, '0') 243 } 244 } 245 return string(buf) 246 } 247 // x.b.abs != 0 248 249 q, r := nat(nil).div(nat(nil), x.a.abs, x.b.abs) 250 251 p := natOne 252 if prec > 0 { 253 p = nat(nil).expNN(natTen, nat(nil).setUint64(uint64(prec)), nil) 254 } 255 256 r = r.mul(r, p) 257 r, r2 := r.div(nat(nil), r, x.b.abs) 258 259 // see if we need to round up 260 r2 = r2.add(r2, r2) 261 if x.b.abs.cmp(r2) <= 0 { 262 r = r.add(r, natOne) 263 if r.cmp(p) >= 0 { 264 q = nat(nil).add(q, natOne) 265 r = nat(nil).sub(r, p) 266 } 267 } 268 269 if x.a.neg { 270 buf = append(buf, '-') 271 } 272 buf = append(buf, q.utoa(10)...) // itoa ignores sign if q == 0 273 274 if prec > 0 { 275 buf = append(buf, '.') 276 rs := r.utoa(10) 277 for i := prec - len(rs); i > 0; i-- { 278 buf = append(buf, '0') 279 } 280 buf = append(buf, rs...) 281 } 282 283 return string(buf) 284 }