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