annotate libgo/go/strconv/decimal.go @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 04ced10e8804
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 // Copyright 2009 The Go Authors. All rights reserved.
kono
parents:
diff changeset
2 // Use of this source code is governed by a BSD-style
kono
parents:
diff changeset
3 // license that can be found in the LICENSE file.
kono
parents:
diff changeset
4
kono
parents:
diff changeset
5 // Multiprecision decimal numbers.
kono
parents:
diff changeset
6 // For floating-point formatting only; not general purpose.
kono
parents:
diff changeset
7 // Only operations are assign and (binary) left/right shift.
kono
parents:
diff changeset
8 // Can do binary floating point in multiprecision decimal precisely
kono
parents:
diff changeset
9 // because 2 divides 10; cannot do decimal floating point
kono
parents:
diff changeset
10 // in multiprecision binary precisely.
kono
parents:
diff changeset
11
kono
parents:
diff changeset
12 package strconv
kono
parents:
diff changeset
13
kono
parents:
diff changeset
14 type decimal struct {
kono
parents:
diff changeset
15 d [800]byte // digits, big-endian representation
kono
parents:
diff changeset
16 nd int // number of digits used
kono
parents:
diff changeset
17 dp int // decimal point
kono
parents:
diff changeset
18 neg bool // negative flag
kono
parents:
diff changeset
19 trunc bool // discarded nonzero digits beyond d[:nd]
kono
parents:
diff changeset
20 }
kono
parents:
diff changeset
21
kono
parents:
diff changeset
22 func (a *decimal) String() string {
kono
parents:
diff changeset
23 n := 10 + a.nd
kono
parents:
diff changeset
24 if a.dp > 0 {
kono
parents:
diff changeset
25 n += a.dp
kono
parents:
diff changeset
26 }
kono
parents:
diff changeset
27 if a.dp < 0 {
kono
parents:
diff changeset
28 n += -a.dp
kono
parents:
diff changeset
29 }
kono
parents:
diff changeset
30
kono
parents:
diff changeset
31 buf := make([]byte, n)
kono
parents:
diff changeset
32 w := 0
kono
parents:
diff changeset
33 switch {
kono
parents:
diff changeset
34 case a.nd == 0:
kono
parents:
diff changeset
35 return "0"
kono
parents:
diff changeset
36
kono
parents:
diff changeset
37 case a.dp <= 0:
kono
parents:
diff changeset
38 // zeros fill space between decimal point and digits
kono
parents:
diff changeset
39 buf[w] = '0'
kono
parents:
diff changeset
40 w++
kono
parents:
diff changeset
41 buf[w] = '.'
kono
parents:
diff changeset
42 w++
kono
parents:
diff changeset
43 w += digitZero(buf[w : w+-a.dp])
kono
parents:
diff changeset
44 w += copy(buf[w:], a.d[0:a.nd])
kono
parents:
diff changeset
45
kono
parents:
diff changeset
46 case a.dp < a.nd:
kono
parents:
diff changeset
47 // decimal point in middle of digits
kono
parents:
diff changeset
48 w += copy(buf[w:], a.d[0:a.dp])
kono
parents:
diff changeset
49 buf[w] = '.'
kono
parents:
diff changeset
50 w++
kono
parents:
diff changeset
51 w += copy(buf[w:], a.d[a.dp:a.nd])
kono
parents:
diff changeset
52
kono
parents:
diff changeset
53 default:
kono
parents:
diff changeset
54 // zeros fill space between digits and decimal point
kono
parents:
diff changeset
55 w += copy(buf[w:], a.d[0:a.nd])
kono
parents:
diff changeset
56 w += digitZero(buf[w : w+a.dp-a.nd])
kono
parents:
diff changeset
57 }
kono
parents:
diff changeset
58 return string(buf[0:w])
kono
parents:
diff changeset
59 }
kono
parents:
diff changeset
60
kono
parents:
diff changeset
61 func digitZero(dst []byte) int {
kono
parents:
diff changeset
62 for i := range dst {
kono
parents:
diff changeset
63 dst[i] = '0'
kono
parents:
diff changeset
64 }
kono
parents:
diff changeset
65 return len(dst)
kono
parents:
diff changeset
66 }
kono
parents:
diff changeset
67
kono
parents:
diff changeset
68 // trim trailing zeros from number.
kono
parents:
diff changeset
69 // (They are meaningless; the decimal point is tracked
kono
parents:
diff changeset
70 // independent of the number of digits.)
kono
parents:
diff changeset
71 func trim(a *decimal) {
kono
parents:
diff changeset
72 for a.nd > 0 && a.d[a.nd-1] == '0' {
kono
parents:
diff changeset
73 a.nd--
kono
parents:
diff changeset
74 }
kono
parents:
diff changeset
75 if a.nd == 0 {
kono
parents:
diff changeset
76 a.dp = 0
kono
parents:
diff changeset
77 }
kono
parents:
diff changeset
78 }
kono
parents:
diff changeset
79
kono
parents:
diff changeset
80 // Assign v to a.
kono
parents:
diff changeset
81 func (a *decimal) Assign(v uint64) {
kono
parents:
diff changeset
82 var buf [24]byte
kono
parents:
diff changeset
83
kono
parents:
diff changeset
84 // Write reversed decimal in buf.
kono
parents:
diff changeset
85 n := 0
kono
parents:
diff changeset
86 for v > 0 {
kono
parents:
diff changeset
87 v1 := v / 10
kono
parents:
diff changeset
88 v -= 10 * v1
kono
parents:
diff changeset
89 buf[n] = byte(v + '0')
kono
parents:
diff changeset
90 n++
kono
parents:
diff changeset
91 v = v1
kono
parents:
diff changeset
92 }
kono
parents:
diff changeset
93
kono
parents:
diff changeset
94 // Reverse again to produce forward decimal in a.d.
kono
parents:
diff changeset
95 a.nd = 0
kono
parents:
diff changeset
96 for n--; n >= 0; n-- {
kono
parents:
diff changeset
97 a.d[a.nd] = buf[n]
kono
parents:
diff changeset
98 a.nd++
kono
parents:
diff changeset
99 }
kono
parents:
diff changeset
100 a.dp = a.nd
kono
parents:
diff changeset
101 trim(a)
kono
parents:
diff changeset
102 }
kono
parents:
diff changeset
103
kono
parents:
diff changeset
104 // Maximum shift that we can do in one pass without overflow.
kono
parents:
diff changeset
105 // A uint has 32 or 64 bits, and we have to be able to accommodate 9<<k.
kono
parents:
diff changeset
106 const uintSize = 32 << (^uint(0) >> 63)
kono
parents:
diff changeset
107 const maxShift = uintSize - 4
kono
parents:
diff changeset
108
kono
parents:
diff changeset
109 // Binary shift right (/ 2) by k bits. k <= maxShift to avoid overflow.
kono
parents:
diff changeset
110 func rightShift(a *decimal, k uint) {
kono
parents:
diff changeset
111 r := 0 // read pointer
kono
parents:
diff changeset
112 w := 0 // write pointer
kono
parents:
diff changeset
113
kono
parents:
diff changeset
114 // Pick up enough leading digits to cover first shift.
kono
parents:
diff changeset
115 var n uint
kono
parents:
diff changeset
116 for ; n>>k == 0; r++ {
kono
parents:
diff changeset
117 if r >= a.nd {
kono
parents:
diff changeset
118 if n == 0 {
kono
parents:
diff changeset
119 // a == 0; shouldn't get here, but handle anyway.
kono
parents:
diff changeset
120 a.nd = 0
kono
parents:
diff changeset
121 return
kono
parents:
diff changeset
122 }
kono
parents:
diff changeset
123 for n>>k == 0 {
kono
parents:
diff changeset
124 n = n * 10
kono
parents:
diff changeset
125 r++
kono
parents:
diff changeset
126 }
kono
parents:
diff changeset
127 break
kono
parents:
diff changeset
128 }
kono
parents:
diff changeset
129 c := uint(a.d[r])
kono
parents:
diff changeset
130 n = n*10 + c - '0'
kono
parents:
diff changeset
131 }
kono
parents:
diff changeset
132 a.dp -= r - 1
kono
parents:
diff changeset
133
kono
parents:
diff changeset
134 var mask uint = (1 << k) - 1
kono
parents:
diff changeset
135
kono
parents:
diff changeset
136 // Pick up a digit, put down a digit.
kono
parents:
diff changeset
137 for ; r < a.nd; r++ {
kono
parents:
diff changeset
138 c := uint(a.d[r])
kono
parents:
diff changeset
139 dig := n >> k
kono
parents:
diff changeset
140 n &= mask
kono
parents:
diff changeset
141 a.d[w] = byte(dig + '0')
kono
parents:
diff changeset
142 w++
kono
parents:
diff changeset
143 n = n*10 + c - '0'
kono
parents:
diff changeset
144 }
kono
parents:
diff changeset
145
kono
parents:
diff changeset
146 // Put down extra digits.
kono
parents:
diff changeset
147 for n > 0 {
kono
parents:
diff changeset
148 dig := n >> k
kono
parents:
diff changeset
149 n &= mask
kono
parents:
diff changeset
150 if w < len(a.d) {
kono
parents:
diff changeset
151 a.d[w] = byte(dig + '0')
kono
parents:
diff changeset
152 w++
kono
parents:
diff changeset
153 } else if dig > 0 {
kono
parents:
diff changeset
154 a.trunc = true
kono
parents:
diff changeset
155 }
kono
parents:
diff changeset
156 n = n * 10
kono
parents:
diff changeset
157 }
kono
parents:
diff changeset
158
kono
parents:
diff changeset
159 a.nd = w
kono
parents:
diff changeset
160 trim(a)
kono
parents:
diff changeset
161 }
kono
parents:
diff changeset
162
kono
parents:
diff changeset
163 // Cheat sheet for left shift: table indexed by shift count giving
kono
parents:
diff changeset
164 // number of new digits that will be introduced by that shift.
kono
parents:
diff changeset
165 //
kono
parents:
diff changeset
166 // For example, leftcheats[4] = {2, "625"}. That means that
kono
parents:
diff changeset
167 // if we are shifting by 4 (multiplying by 16), it will add 2 digits
kono
parents:
diff changeset
168 // when the string prefix is "625" through "999", and one fewer digit
kono
parents:
diff changeset
169 // if the string prefix is "000" through "624".
kono
parents:
diff changeset
170 //
kono
parents:
diff changeset
171 // Credit for this trick goes to Ken.
kono
parents:
diff changeset
172
kono
parents:
diff changeset
173 type leftCheat struct {
kono
parents:
diff changeset
174 delta int // number of new digits
kono
parents:
diff changeset
175 cutoff string // minus one digit if original < a.
kono
parents:
diff changeset
176 }
kono
parents:
diff changeset
177
kono
parents:
diff changeset
178 var leftcheats = []leftCheat{
kono
parents:
diff changeset
179 // Leading digits of 1/2^i = 5^i.
kono
parents:
diff changeset
180 // 5^23 is not an exact 64-bit floating point number,
kono
parents:
diff changeset
181 // so have to use bc for the math.
kono
parents:
diff changeset
182 // Go up to 60 to be large enough for 32bit and 64bit platforms.
kono
parents:
diff changeset
183 /*
kono
parents:
diff changeset
184 seq 60 | sed 's/^/5^/' | bc |
kono
parents:
diff changeset
185 awk 'BEGIN{ print "\t{ 0, \"\" }," }
kono
parents:
diff changeset
186 {
kono
parents:
diff changeset
187 log2 = log(2)/log(10)
kono
parents:
diff changeset
188 printf("\t{ %d, \"%s\" },\t// * %d\n",
kono
parents:
diff changeset
189 int(log2*NR+1), $0, 2**NR)
kono
parents:
diff changeset
190 }'
kono
parents:
diff changeset
191 */
kono
parents:
diff changeset
192 {0, ""},
kono
parents:
diff changeset
193 {1, "5"}, // * 2
kono
parents:
diff changeset
194 {1, "25"}, // * 4
kono
parents:
diff changeset
195 {1, "125"}, // * 8
kono
parents:
diff changeset
196 {2, "625"}, // * 16
kono
parents:
diff changeset
197 {2, "3125"}, // * 32
kono
parents:
diff changeset
198 {2, "15625"}, // * 64
kono
parents:
diff changeset
199 {3, "78125"}, // * 128
kono
parents:
diff changeset
200 {3, "390625"}, // * 256
kono
parents:
diff changeset
201 {3, "1953125"}, // * 512
kono
parents:
diff changeset
202 {4, "9765625"}, // * 1024
kono
parents:
diff changeset
203 {4, "48828125"}, // * 2048
kono
parents:
diff changeset
204 {4, "244140625"}, // * 4096
kono
parents:
diff changeset
205 {4, "1220703125"}, // * 8192
kono
parents:
diff changeset
206 {5, "6103515625"}, // * 16384
kono
parents:
diff changeset
207 {5, "30517578125"}, // * 32768
kono
parents:
diff changeset
208 {5, "152587890625"}, // * 65536
kono
parents:
diff changeset
209 {6, "762939453125"}, // * 131072
kono
parents:
diff changeset
210 {6, "3814697265625"}, // * 262144
kono
parents:
diff changeset
211 {6, "19073486328125"}, // * 524288
kono
parents:
diff changeset
212 {7, "95367431640625"}, // * 1048576
kono
parents:
diff changeset
213 {7, "476837158203125"}, // * 2097152
kono
parents:
diff changeset
214 {7, "2384185791015625"}, // * 4194304
kono
parents:
diff changeset
215 {7, "11920928955078125"}, // * 8388608
kono
parents:
diff changeset
216 {8, "59604644775390625"}, // * 16777216
kono
parents:
diff changeset
217 {8, "298023223876953125"}, // * 33554432
kono
parents:
diff changeset
218 {8, "1490116119384765625"}, // * 67108864
kono
parents:
diff changeset
219 {9, "7450580596923828125"}, // * 134217728
kono
parents:
diff changeset
220 {9, "37252902984619140625"}, // * 268435456
kono
parents:
diff changeset
221 {9, "186264514923095703125"}, // * 536870912
kono
parents:
diff changeset
222 {10, "931322574615478515625"}, // * 1073741824
kono
parents:
diff changeset
223 {10, "4656612873077392578125"}, // * 2147483648
kono
parents:
diff changeset
224 {10, "23283064365386962890625"}, // * 4294967296
kono
parents:
diff changeset
225 {10, "116415321826934814453125"}, // * 8589934592
kono
parents:
diff changeset
226 {11, "582076609134674072265625"}, // * 17179869184
kono
parents:
diff changeset
227 {11, "2910383045673370361328125"}, // * 34359738368
kono
parents:
diff changeset
228 {11, "14551915228366851806640625"}, // * 68719476736
kono
parents:
diff changeset
229 {12, "72759576141834259033203125"}, // * 137438953472
kono
parents:
diff changeset
230 {12, "363797880709171295166015625"}, // * 274877906944
kono
parents:
diff changeset
231 {12, "1818989403545856475830078125"}, // * 549755813888
kono
parents:
diff changeset
232 {13, "9094947017729282379150390625"}, // * 1099511627776
kono
parents:
diff changeset
233 {13, "45474735088646411895751953125"}, // * 2199023255552
kono
parents:
diff changeset
234 {13, "227373675443232059478759765625"}, // * 4398046511104
kono
parents:
diff changeset
235 {13, "1136868377216160297393798828125"}, // * 8796093022208
kono
parents:
diff changeset
236 {14, "5684341886080801486968994140625"}, // * 17592186044416
kono
parents:
diff changeset
237 {14, "28421709430404007434844970703125"}, // * 35184372088832
kono
parents:
diff changeset
238 {14, "142108547152020037174224853515625"}, // * 70368744177664
kono
parents:
diff changeset
239 {15, "710542735760100185871124267578125"}, // * 140737488355328
kono
parents:
diff changeset
240 {15, "3552713678800500929355621337890625"}, // * 281474976710656
kono
parents:
diff changeset
241 {15, "17763568394002504646778106689453125"}, // * 562949953421312
kono
parents:
diff changeset
242 {16, "88817841970012523233890533447265625"}, // * 1125899906842624
kono
parents:
diff changeset
243 {16, "444089209850062616169452667236328125"}, // * 2251799813685248
kono
parents:
diff changeset
244 {16, "2220446049250313080847263336181640625"}, // * 4503599627370496
kono
parents:
diff changeset
245 {16, "11102230246251565404236316680908203125"}, // * 9007199254740992
kono
parents:
diff changeset
246 {17, "55511151231257827021181583404541015625"}, // * 18014398509481984
kono
parents:
diff changeset
247 {17, "277555756156289135105907917022705078125"}, // * 36028797018963968
kono
parents:
diff changeset
248 {17, "1387778780781445675529539585113525390625"}, // * 72057594037927936
kono
parents:
diff changeset
249 {18, "6938893903907228377647697925567626953125"}, // * 144115188075855872
kono
parents:
diff changeset
250 {18, "34694469519536141888238489627838134765625"}, // * 288230376151711744
kono
parents:
diff changeset
251 {18, "173472347597680709441192448139190673828125"}, // * 576460752303423488
kono
parents:
diff changeset
252 {19, "867361737988403547205962240695953369140625"}, // * 1152921504606846976
kono
parents:
diff changeset
253 }
kono
parents:
diff changeset
254
kono
parents:
diff changeset
255 // Is the leading prefix of b lexicographically less than s?
kono
parents:
diff changeset
256 func prefixIsLessThan(b []byte, s string) bool {
kono
parents:
diff changeset
257 for i := 0; i < len(s); i++ {
kono
parents:
diff changeset
258 if i >= len(b) {
kono
parents:
diff changeset
259 return true
kono
parents:
diff changeset
260 }
kono
parents:
diff changeset
261 if b[i] != s[i] {
kono
parents:
diff changeset
262 return b[i] < s[i]
kono
parents:
diff changeset
263 }
kono
parents:
diff changeset
264 }
kono
parents:
diff changeset
265 return false
kono
parents:
diff changeset
266 }
kono
parents:
diff changeset
267
kono
parents:
diff changeset
268 // Binary shift left (* 2) by k bits. k <= maxShift to avoid overflow.
kono
parents:
diff changeset
269 func leftShift(a *decimal, k uint) {
kono
parents:
diff changeset
270 delta := leftcheats[k].delta
kono
parents:
diff changeset
271 if prefixIsLessThan(a.d[0:a.nd], leftcheats[k].cutoff) {
kono
parents:
diff changeset
272 delta--
kono
parents:
diff changeset
273 }
kono
parents:
diff changeset
274
kono
parents:
diff changeset
275 r := a.nd // read index
kono
parents:
diff changeset
276 w := a.nd + delta // write index
kono
parents:
diff changeset
277
kono
parents:
diff changeset
278 // Pick up a digit, put down a digit.
kono
parents:
diff changeset
279 var n uint
kono
parents:
diff changeset
280 for r--; r >= 0; r-- {
kono
parents:
diff changeset
281 n += (uint(a.d[r]) - '0') << k
kono
parents:
diff changeset
282 quo := n / 10
kono
parents:
diff changeset
283 rem := n - 10*quo
kono
parents:
diff changeset
284 w--
kono
parents:
diff changeset
285 if w < len(a.d) {
kono
parents:
diff changeset
286 a.d[w] = byte(rem + '0')
kono
parents:
diff changeset
287 } else if rem != 0 {
kono
parents:
diff changeset
288 a.trunc = true
kono
parents:
diff changeset
289 }
kono
parents:
diff changeset
290 n = quo
kono
parents:
diff changeset
291 }
kono
parents:
diff changeset
292
kono
parents:
diff changeset
293 // Put down extra digits.
kono
parents:
diff changeset
294 for n > 0 {
kono
parents:
diff changeset
295 quo := n / 10
kono
parents:
diff changeset
296 rem := n - 10*quo
kono
parents:
diff changeset
297 w--
kono
parents:
diff changeset
298 if w < len(a.d) {
kono
parents:
diff changeset
299 a.d[w] = byte(rem + '0')
kono
parents:
diff changeset
300 } else if rem != 0 {
kono
parents:
diff changeset
301 a.trunc = true
kono
parents:
diff changeset
302 }
kono
parents:
diff changeset
303 n = quo
kono
parents:
diff changeset
304 }
kono
parents:
diff changeset
305
kono
parents:
diff changeset
306 a.nd += delta
kono
parents:
diff changeset
307 if a.nd >= len(a.d) {
kono
parents:
diff changeset
308 a.nd = len(a.d)
kono
parents:
diff changeset
309 }
kono
parents:
diff changeset
310 a.dp += delta
kono
parents:
diff changeset
311 trim(a)
kono
parents:
diff changeset
312 }
kono
parents:
diff changeset
313
kono
parents:
diff changeset
314 // Binary shift left (k > 0) or right (k < 0).
kono
parents:
diff changeset
315 func (a *decimal) Shift(k int) {
kono
parents:
diff changeset
316 switch {
kono
parents:
diff changeset
317 case a.nd == 0:
kono
parents:
diff changeset
318 // nothing to do: a == 0
kono
parents:
diff changeset
319 case k > 0:
kono
parents:
diff changeset
320 for k > maxShift {
kono
parents:
diff changeset
321 leftShift(a, maxShift)
kono
parents:
diff changeset
322 k -= maxShift
kono
parents:
diff changeset
323 }
kono
parents:
diff changeset
324 leftShift(a, uint(k))
kono
parents:
diff changeset
325 case k < 0:
kono
parents:
diff changeset
326 for k < -maxShift {
kono
parents:
diff changeset
327 rightShift(a, maxShift)
kono
parents:
diff changeset
328 k += maxShift
kono
parents:
diff changeset
329 }
kono
parents:
diff changeset
330 rightShift(a, uint(-k))
kono
parents:
diff changeset
331 }
kono
parents:
diff changeset
332 }
kono
parents:
diff changeset
333
kono
parents:
diff changeset
334 // If we chop a at nd digits, should we round up?
kono
parents:
diff changeset
335 func shouldRoundUp(a *decimal, nd int) bool {
kono
parents:
diff changeset
336 if nd < 0 || nd >= a.nd {
kono
parents:
diff changeset
337 return false
kono
parents:
diff changeset
338 }
kono
parents:
diff changeset
339 if a.d[nd] == '5' && nd+1 == a.nd { // exactly halfway - round to even
kono
parents:
diff changeset
340 // if we truncated, a little higher than what's recorded - always round up
kono
parents:
diff changeset
341 if a.trunc {
kono
parents:
diff changeset
342 return true
kono
parents:
diff changeset
343 }
kono
parents:
diff changeset
344 return nd > 0 && (a.d[nd-1]-'0')%2 != 0
kono
parents:
diff changeset
345 }
kono
parents:
diff changeset
346 // not halfway - digit tells all
kono
parents:
diff changeset
347 return a.d[nd] >= '5'
kono
parents:
diff changeset
348 }
kono
parents:
diff changeset
349
kono
parents:
diff changeset
350 // Round a to nd digits (or fewer).
kono
parents:
diff changeset
351 // If nd is zero, it means we're rounding
kono
parents:
diff changeset
352 // just to the left of the digits, as in
kono
parents:
diff changeset
353 // 0.09 -> 0.1.
kono
parents:
diff changeset
354 func (a *decimal) Round(nd int) {
kono
parents:
diff changeset
355 if nd < 0 || nd >= a.nd {
kono
parents:
diff changeset
356 return
kono
parents:
diff changeset
357 }
kono
parents:
diff changeset
358 if shouldRoundUp(a, nd) {
kono
parents:
diff changeset
359 a.RoundUp(nd)
kono
parents:
diff changeset
360 } else {
kono
parents:
diff changeset
361 a.RoundDown(nd)
kono
parents:
diff changeset
362 }
kono
parents:
diff changeset
363 }
kono
parents:
diff changeset
364
kono
parents:
diff changeset
365 // Round a down to nd digits (or fewer).
kono
parents:
diff changeset
366 func (a *decimal) RoundDown(nd int) {
kono
parents:
diff changeset
367 if nd < 0 || nd >= a.nd {
kono
parents:
diff changeset
368 return
kono
parents:
diff changeset
369 }
kono
parents:
diff changeset
370 a.nd = nd
kono
parents:
diff changeset
371 trim(a)
kono
parents:
diff changeset
372 }
kono
parents:
diff changeset
373
kono
parents:
diff changeset
374 // Round a up to nd digits (or fewer).
kono
parents:
diff changeset
375 func (a *decimal) RoundUp(nd int) {
kono
parents:
diff changeset
376 if nd < 0 || nd >= a.nd {
kono
parents:
diff changeset
377 return
kono
parents:
diff changeset
378 }
kono
parents:
diff changeset
379
kono
parents:
diff changeset
380 // round up
kono
parents:
diff changeset
381 for i := nd - 1; i >= 0; i-- {
kono
parents:
diff changeset
382 c := a.d[i]
kono
parents:
diff changeset
383 if c < '9' { // can stop after this digit
kono
parents:
diff changeset
384 a.d[i]++
kono
parents:
diff changeset
385 a.nd = i + 1
kono
parents:
diff changeset
386 return
kono
parents:
diff changeset
387 }
kono
parents:
diff changeset
388 }
kono
parents:
diff changeset
389
kono
parents:
diff changeset
390 // Number is all 9s.
kono
parents:
diff changeset
391 // Change to single 1 with adjusted decimal point.
kono
parents:
diff changeset
392 a.d[0] = '1'
kono
parents:
diff changeset
393 a.nd = 1
kono
parents:
diff changeset
394 a.dp++
kono
parents:
diff changeset
395 }
kono
parents:
diff changeset
396
kono
parents:
diff changeset
397 // Extract integer part, rounded appropriately.
kono
parents:
diff changeset
398 // No guarantees about overflow.
kono
parents:
diff changeset
399 func (a *decimal) RoundedInteger() uint64 {
kono
parents:
diff changeset
400 if a.dp > 20 {
kono
parents:
diff changeset
401 return 0xFFFFFFFFFFFFFFFF
kono
parents:
diff changeset
402 }
kono
parents:
diff changeset
403 var i int
kono
parents:
diff changeset
404 n := uint64(0)
kono
parents:
diff changeset
405 for i = 0; i < a.dp && i < a.nd; i++ {
kono
parents:
diff changeset
406 n = n*10 + uint64(a.d[i]-'0')
kono
parents:
diff changeset
407 }
kono
parents:
diff changeset
408 for ; i < a.dp; i++ {
kono
parents:
diff changeset
409 n *= 10
kono
parents:
diff changeset
410 }
kono
parents:
diff changeset
411 if shouldRoundUp(a, a.dp) {
kono
parents:
diff changeset
412 n++
kono
parents:
diff changeset
413 }
kono
parents:
diff changeset
414 return n
kono
parents:
diff changeset
415 }