ratconv.go 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  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. // This file implements rat-to-string conversion functions.
  5. package big
  6. import (
  7. "errors"
  8. "fmt"
  9. "io"
  10. "strconv"
  11. "strings"
  12. )
  13. func ratTok(ch rune) bool {
  14. return strings.ContainsRune("+-/0123456789.eE", ch)
  15. }
  16. var ratZero Rat
  17. var _ fmt.Scanner = &ratZero // *Rat must implement fmt.Scanner
  18. // Scan is a support routine for fmt.Scanner. It accepts the formats
  19. // 'e', 'E', 'f', 'F', 'g', 'G', and 'v'. All formats are equivalent.
  20. func (z *Rat) Scan(s fmt.ScanState, ch rune) error {
  21. tok, err := s.Token(true, ratTok)
  22. if err != nil {
  23. return err
  24. }
  25. if !strings.ContainsRune("efgEFGv", ch) {
  26. return errors.New("Rat.Scan: invalid verb")
  27. }
  28. if _, ok := z.SetString(string(tok)); !ok {
  29. return errors.New("Rat.Scan: invalid syntax")
  30. }
  31. return nil
  32. }
  33. // SetString sets z to the value of s and returns z and a boolean indicating
  34. // success. s can be given as a (possibly signed) fraction "a/b", or as a
  35. // floating-point number optionally followed by an exponent.
  36. // If a fraction is provided, both the dividend and the divisor may be a
  37. // decimal integer or independently use a prefix of ``0b'', ``0'' or ``0o'',
  38. // or ``0x'' (or their upper-case variants) to denote a binary, octal, or
  39. // hexadecimal integer, respectively. The divisor may not be signed.
  40. // If a floating-point number is provided, it may be in decimal form or
  41. // use any of the same prefixes as above but for ``0'' to denote a non-decimal
  42. // mantissa. A leading ``0'' is considered a decimal leading 0; it does not
  43. // indicate octal representation in this case.
  44. // An optional base-10 ``e'' or base-2 ``p'' (or their upper-case variants)
  45. // exponent may be provided as well, except for hexadecimal floats which
  46. // only accept an (optional) ``p'' exponent (because an ``e'' or ``E'' cannot
  47. // be distinguished from a mantissa digit). If the exponent's absolute value
  48. // is too large, the operation may fail.
  49. // The entire string, not just a prefix, must be valid for success. If the
  50. // operation failed, the value of z is undefined but the returned value is nil.
  51. func (z *Rat) SetString(s string) (*Rat, bool) {
  52. if len(s) == 0 {
  53. return nil, false
  54. }
  55. // len(s) > 0
  56. // parse fraction a/b, if any
  57. if sep := strings.Index(s, "/"); sep >= 0 {
  58. if _, ok := z.a.SetString(s[:sep], 0); !ok {
  59. return nil, false
  60. }
  61. r := strings.NewReader(s[sep+1:])
  62. var err error
  63. if z.b.abs, _, _, err = z.b.abs.scan(r, 0, false); err != nil {
  64. return nil, false
  65. }
  66. // entire string must have been consumed
  67. if _, err = r.ReadByte(); err != io.EOF {
  68. return nil, false
  69. }
  70. if len(z.b.abs) == 0 {
  71. return nil, false
  72. }
  73. return z.norm(), true
  74. }
  75. // parse floating-point number
  76. r := strings.NewReader(s)
  77. // sign
  78. neg, err := scanSign(r)
  79. if err != nil {
  80. return nil, false
  81. }
  82. // mantissa
  83. var base int
  84. var fcount int // fractional digit count; valid if <= 0
  85. z.a.abs, base, fcount, err = z.a.abs.scan(r, 0, true)
  86. if err != nil {
  87. return nil, false
  88. }
  89. // exponent
  90. var exp int64
  91. var ebase int
  92. exp, ebase, err = scanExponent(r, true, true)
  93. if err != nil {
  94. return nil, false
  95. }
  96. // there should be no unread characters left
  97. if _, err = r.ReadByte(); err != io.EOF {
  98. return nil, false
  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. // The mantissa may have a radix point (fcount <= 0) and there
  106. // may be a nonzero exponent exp. The radix point amounts to a
  107. // division by base**(-fcount), which equals a multiplication by
  108. // base**fcount. An exponent means multiplication by ebase**exp.
  109. // Multiplications are commutative, so we can apply them in any
  110. // order. We only have powers of 2 and 10, and we split powers
  111. // of 10 into the product of the same powers of 2 and 5. This
  112. // may reduce the size of shift/multiplication factors or
  113. // divisors required to create the final fraction, depending
  114. // on the actual floating-point value.
  115. // determine binary or decimal exponent contribution of radix point
  116. var exp2, exp5 int64
  117. if fcount < 0 {
  118. // The mantissa has a radix point ddd.dddd; and
  119. // -fcount is the number of digits to the right
  120. // of '.'. Adjust relevant exponent accordingly.
  121. d := int64(fcount)
  122. switch base {
  123. case 10:
  124. exp5 = d
  125. fallthrough // 10**e == 5**e * 2**e
  126. case 2:
  127. exp2 = d
  128. case 8:
  129. exp2 = d * 3 // octal digits are 3 bits each
  130. case 16:
  131. exp2 = d * 4 // hexadecimal digits are 4 bits each
  132. default:
  133. panic("unexpected mantissa base")
  134. }
  135. // fcount consumed - not needed anymore
  136. }
  137. // take actual exponent into account
  138. switch ebase {
  139. case 10:
  140. exp5 += exp
  141. fallthrough // see fallthrough above
  142. case 2:
  143. exp2 += exp
  144. default:
  145. panic("unexpected exponent base")
  146. }
  147. // exp consumed - not needed anymore
  148. // apply exp5 contributions
  149. // (start with exp5 so the numbers to multiply are smaller)
  150. if exp5 != 0 {
  151. n := exp5
  152. if n < 0 {
  153. n = -n
  154. if n < 0 {
  155. // This can occur if -n overflows. -(-1 << 63) would become
  156. // -1 << 63, which is still negative.
  157. return nil, false
  158. }
  159. }
  160. if n > 1e6 {
  161. return nil, false // avoid excessively large exponents
  162. }
  163. pow5 := z.b.abs.expNN(natFive, nat(nil).setWord(Word(n)), nil) // use underlying array of z.b.abs
  164. if exp5 > 0 {
  165. z.a.abs = z.a.abs.mul(z.a.abs, pow5)
  166. z.b.abs = z.b.abs.setWord(1)
  167. } else {
  168. z.b.abs = pow5
  169. }
  170. } else {
  171. z.b.abs = z.b.abs.setWord(1)
  172. }
  173. // apply exp2 contributions
  174. if exp2 < -1e7 || exp2 > 1e7 {
  175. return nil, false // avoid excessively large exponents
  176. }
  177. if exp2 > 0 {
  178. z.a.abs = z.a.abs.shl(z.a.abs, uint(exp2))
  179. } else if exp2 < 0 {
  180. z.b.abs = z.b.abs.shl(z.b.abs, uint(-exp2))
  181. }
  182. z.a.neg = neg && len(z.a.abs) > 0 // 0 has no sign
  183. return z.norm(), true
  184. }
  185. // scanExponent scans the longest possible prefix of r representing a base 10
  186. // (``e'', ``E'') or a base 2 (``p'', ``P'') exponent, if any. It returns the
  187. // exponent, the exponent base (10 or 2), or a read or syntax error, if any.
  188. //
  189. // If sepOk is set, an underscore character ``_'' may appear between successive
  190. // exponent digits; such underscores do not change the value of the exponent.
  191. // Incorrect placement of underscores is reported as an error if there are no
  192. // other errors. If sepOk is not set, underscores are not recognized and thus
  193. // terminate scanning like any other character that is not a valid digit.
  194. //
  195. // exponent = ( "e" | "E" | "p" | "P" ) [ sign ] digits .
  196. // sign = "+" | "-" .
  197. // digits = digit { [ '_' ] digit } .
  198. // digit = "0" ... "9" .
  199. //
  200. // A base 2 exponent is only permitted if base2ok is set.
  201. func scanExponent(r io.ByteScanner, base2ok, sepOk bool) (exp int64, base int, err error) {
  202. // one char look-ahead
  203. ch, err := r.ReadByte()
  204. if err != nil {
  205. if err == io.EOF {
  206. err = nil
  207. }
  208. return 0, 10, err
  209. }
  210. // exponent char
  211. switch ch {
  212. case 'e', 'E':
  213. base = 10
  214. case 'p', 'P':
  215. if base2ok {
  216. base = 2
  217. break // ok
  218. }
  219. fallthrough // binary exponent not permitted
  220. default:
  221. r.UnreadByte() // ch does not belong to exponent anymore
  222. return 0, 10, nil
  223. }
  224. // sign
  225. var digits []byte
  226. ch, err = r.ReadByte()
  227. if err == nil && (ch == '+' || ch == '-') {
  228. if ch == '-' {
  229. digits = append(digits, '-')
  230. }
  231. ch, err = r.ReadByte()
  232. }
  233. // prev encodes the previously seen char: it is one
  234. // of '_', '0' (a digit), or '.' (anything else). A
  235. // valid separator '_' may only occur after a digit.
  236. prev := '.'
  237. invalSep := false
  238. // exponent value
  239. hasDigits := false
  240. for err == nil {
  241. if '0' <= ch && ch <= '9' {
  242. digits = append(digits, ch)
  243. prev = '0'
  244. hasDigits = true
  245. } else if ch == '_' && sepOk {
  246. if prev != '0' {
  247. invalSep = true
  248. }
  249. prev = '_'
  250. } else {
  251. r.UnreadByte() // ch does not belong to number anymore
  252. break
  253. }
  254. ch, err = r.ReadByte()
  255. }
  256. if err == io.EOF {
  257. err = nil
  258. }
  259. if err == nil && !hasDigits {
  260. err = errNoDigits
  261. }
  262. if err == nil {
  263. exp, err = strconv.ParseInt(string(digits), 10, 64)
  264. }
  265. // other errors take precedence over invalid separators
  266. if err == nil && (invalSep || prev == '_') {
  267. err = errInvalSep
  268. }
  269. return
  270. }
  271. // String returns a string representation of x in the form "a/b" (even if b == 1).
  272. func (x *Rat) String() string {
  273. return string(x.marshal())
  274. }
  275. // marshal implements String returning a slice of bytes
  276. func (x *Rat) marshal() []byte {
  277. var buf []byte
  278. buf = x.a.Append(buf, 10)
  279. buf = append(buf, '/')
  280. if len(x.b.abs) != 0 {
  281. buf = x.b.Append(buf, 10)
  282. } else {
  283. buf = append(buf, '1')
  284. }
  285. return buf
  286. }
  287. // RatString returns a string representation of x in the form "a/b" if b != 1,
  288. // and in the form "a" if b == 1.
  289. func (x *Rat) RatString() string {
  290. if x.IsInt() {
  291. return x.a.String()
  292. }
  293. return x.String()
  294. }
  295. // FloatString returns a string representation of x in decimal form with prec
  296. // digits of precision after the radix point. The last digit is rounded to
  297. // nearest, with halves rounded away from zero.
  298. func (x *Rat) FloatString(prec int) string {
  299. var buf []byte
  300. if x.IsInt() {
  301. buf = x.a.Append(buf, 10)
  302. if prec > 0 {
  303. buf = append(buf, '.')
  304. for i := prec; i > 0; i-- {
  305. buf = append(buf, '0')
  306. }
  307. }
  308. return string(buf)
  309. }
  310. // x.b.abs != 0
  311. q, r := nat(nil).div(nat(nil), x.a.abs, x.b.abs)
  312. p := natOne
  313. if prec > 0 {
  314. p = nat(nil).expNN(natTen, nat(nil).setUint64(uint64(prec)), nil)
  315. }
  316. r = r.mul(r, p)
  317. r, r2 := r.div(nat(nil), r, x.b.abs)
  318. // see if we need to round up
  319. r2 = r2.add(r2, r2)
  320. if x.b.abs.cmp(r2) <= 0 {
  321. r = r.add(r, natOne)
  322. if r.cmp(p) >= 0 {
  323. q = nat(nil).add(q, natOne)
  324. r = nat(nil).sub(r, p)
  325. }
  326. }
  327. if x.a.neg {
  328. buf = append(buf, '-')
  329. }
  330. buf = append(buf, q.utoa(10)...) // itoa ignores sign if q == 0
  331. if prec > 0 {
  332. buf = append(buf, '.')
  333. rs := r.utoa(10)
  334. for i := prec - len(rs); i > 0; i-- {
  335. buf = append(buf, '0')
  336. }
  337. buf = append(buf, rs...)
  338. }
  339. return string(buf)
  340. }