Source file src/math/big/decimal.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 multi-precision decimal numbers. 6 // The implementation is for float to decimal conversion only; 7 // not general purpose use. 8 // The only operations are precise conversion from binary to 9 // decimal and rounding. 10 // 11 // The key observation and some code (shr) is borrowed from 12 // strconv/decimal.go: conversion of binary fractional values can be done 13 // precisely in multi-precision decimal because 2 divides 10 (required for 14 // >> of mantissa); but conversion of decimal floating-point values cannot 15 // be done precisely in binary representation. 16 // 17 // In contrast to strconv/decimal.go, only right shift is implemented in 18 // decimal format - left shift can be done precisely in binary format. 19 20 package big 21 22 // A decimal represents an unsigned floating-point number in decimal representation. 23 // The value of a non-zero decimal d is d.mant * 10**d.exp with 0.1 <= d.mant < 1, 24 // with the most-significant mantissa digit at index 0. For the zero decimal, the 25 // mantissa length and exponent are 0. 26 // The zero value for decimal represents a ready-to-use 0.0. 27 type decimal struct { 28 mant []byte // mantissa ASCII digits, big-endian 29 exp int // exponent 30 } 31 32 // at returns the i'th mantissa digit, starting with the most significant digit at 0. 33 func (d *decimal) at(i int) byte { 34 if 0 <= i && i < len(d.mant) { 35 return d.mant[i] 36 } 37 return '0' 38 } 39 40 // Maximum shift amount that can be done in one pass without overflow. 41 // A Word has _W bits and (1<<maxShift - 1)*10 + 9 must fit into Word. 42 const maxShift = _W - 4 43 44 // TODO(gri) Since we know the desired decimal precision when converting 45 // a floating-point number, we may be able to limit the number of decimal 46 // digits that need to be computed by init by providing an additional 47 // precision argument and keeping track of when a number was truncated early 48 // (equivalent of "sticky bit" in binary rounding). 49 50 // TODO(gri) Along the same lines, enforce some limit to shift magnitudes 51 // to avoid "infinitely" long running conversions (until we run out of space). 52 53 // Init initializes x to the decimal representation of m << shift (for 54 // shift >= 0), or m >> -shift (for shift < 0). 55 func (x *decimal) init(m nat, shift int) { 56 // special case 0 57 if len(m) == 0 { 58 x.mant = x.mant[:0] 59 x.exp = 0 60 return 61 } 62 63 // Optimization: If we need to shift right, first remove any trailing 64 // zero bits from m to reduce shift amount that needs to be done in 65 // decimal format (since that is likely slower). 66 if shift < 0 { 67 ntz := m.trailingZeroBits() 68 s := uint(-shift) 69 if s >= ntz { 70 s = ntz // shift at most ntz bits 71 } 72 m = nat(nil).shr(m, s) 73 shift += int(s) 74 } 75 76 // Do any shift left in binary representation. 77 if shift > 0 { 78 m = nat(nil).shl(m, uint(shift)) 79 shift = 0 80 } 81 82 // Convert mantissa into decimal representation. 83 s := m.utoa(10) 84 n := len(s) 85 x.exp = n 86 // Trim trailing zeros; instead the exponent is tracking 87 // the decimal point independent of the number of digits. 88 for n > 0 && s[n-1] == '0' { 89 n-- 90 } 91 x.mant = append(x.mant[:0], s[:n]...) 92 93 // Do any (remaining) shift right in decimal representation. 94 if shift < 0 { 95 for shift < -maxShift { 96 shr(x, maxShift) 97 shift += maxShift 98 } 99 shr(x, uint(-shift)) 100 } 101 } 102 103 // shr implements x >> s, for s <= maxShift. 104 func shr(x *decimal, s uint) { 105 // Division by 1<<s using shift-and-subtract algorithm. 106 107 // pick up enough leading digits to cover first shift 108 r := 0 // read index 109 var n Word 110 for n>>s == 0 && r < len(x.mant) { 111 ch := Word(x.mant[r]) 112 r++ 113 n = n*10 + ch - '0' 114 } 115 if n == 0 { 116 // x == 0; shouldn't get here, but handle anyway 117 x.mant = x.mant[:0] 118 return 119 } 120 for n>>s == 0 { 121 r++ 122 n *= 10 123 } 124 x.exp += 1 - r 125 126 // read a digit, write a digit 127 w := 0 // write index 128 mask := Word(1)<<s - 1 129 for r < len(x.mant) { 130 ch := Word(x.mant[r]) 131 r++ 132 d := n >> s 133 n &= mask // n -= d << s 134 x.mant[w] = byte(d + '0') 135 w++ 136 n = n*10 + ch - '0' 137 } 138 139 // write extra digits that still fit 140 for n > 0 && w < len(x.mant) { 141 d := n >> s 142 n &= mask 143 x.mant[w] = byte(d + '0') 144 w++ 145 n = n * 10 146 } 147 x.mant = x.mant[:w] // the number may be shorter (e.g. 1024 >> 10) 148 149 // append additional digits that didn't fit 150 for n > 0 { 151 d := n >> s 152 n &= mask 153 x.mant = append(x.mant, byte(d+'0')) 154 n = n * 10 155 } 156 157 trim(x) 158 } 159 160 func (x *decimal) String() string { 161 if len(x.mant) == 0 { 162 return "0" 163 } 164 165 var buf []byte 166 switch { 167 case x.exp <= 0: 168 // 0.00ddd 169 buf = make([]byte, 0, 2+(-x.exp)+len(x.mant)) 170 buf = append(buf, "0."...) 171 buf = appendZeros(buf, -x.exp) 172 buf = append(buf, x.mant...) 173 174 case /* 0 < */ x.exp < len(x.mant): 175 // dd.ddd 176 buf = make([]byte, 0, 1+len(x.mant)) 177 buf = append(buf, x.mant[:x.exp]...) 178 buf = append(buf, '.') 179 buf = append(buf, x.mant[x.exp:]...) 180 181 default: // len(x.mant) <= x.exp 182 // ddd00 183 buf = make([]byte, 0, x.exp) 184 buf = append(buf, x.mant...) 185 buf = appendZeros(buf, x.exp-len(x.mant)) 186 } 187 188 return string(buf) 189 } 190 191 // appendZeros appends n 0 digits to buf and returns buf. 192 func appendZeros(buf []byte, n int) []byte { 193 for ; n > 0; n-- { 194 buf = append(buf, '0') 195 } 196 return buf 197 } 198 199 // shouldRoundUp reports if x should be rounded up 200 // if shortened to n digits. n must be a valid index 201 // for x.mant. 202 func shouldRoundUp(x *decimal, n int) bool { 203 if x.mant[n] == '5' && n+1 == len(x.mant) { 204 // exactly halfway - round to even 205 return n > 0 && (x.mant[n-1]-'0')&1 != 0 206 } 207 // not halfway - digit tells all (x.mant has no trailing zeros) 208 return x.mant[n] >= '5' 209 } 210 211 // round sets x to (at most) n mantissa digits by rounding it 212 // to the nearest even value with n (or fever) mantissa digits. 213 // If n < 0, x remains unchanged. 214 func (x *decimal) round(n int) { 215 if n < 0 || n >= len(x.mant) { 216 return // nothing to do 217 } 218 219 if shouldRoundUp(x, n) { 220 x.roundUp(n) 221 } else { 222 x.roundDown(n) 223 } 224 } 225 226 func (x *decimal) roundUp(n int) { 227 if n < 0 || n >= len(x.mant) { 228 return // nothing to do 229 } 230 // 0 <= n < len(x.mant) 231 232 // find first digit < '9' 233 for n > 0 && x.mant[n-1] >= '9' { 234 n-- 235 } 236 237 if n == 0 { 238 // all digits are '9's => round up to '1' and update exponent 239 x.mant[0] = '1' // ok since len(x.mant) > n 240 x.mant = x.mant[:1] 241 x.exp++ 242 return 243 } 244 245 // n > 0 && x.mant[n-1] < '9' 246 x.mant[n-1]++ 247 x.mant = x.mant[:n] 248 // x already trimmed 249 } 250 251 func (x *decimal) roundDown(n int) { 252 if n < 0 || n >= len(x.mant) { 253 return // nothing to do 254 } 255 x.mant = x.mant[:n] 256 trim(x) 257 } 258 259 // trim cuts off any trailing zeros from x's mantissa; 260 // they are meaningless for the value of x. 261 func trim(x *decimal) { 262 i := len(x.mant) 263 for i > 0 && x.mant[i-1] == '0' { 264 i-- 265 } 266 x.mant = x.mant[:i] 267 if i == 0 { 268 x.exp = 0 269 } 270 } 271