github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/pingcap/tidb/mysql/decimal.go (about) 1 // The MIT License (MIT) 2 3 // Copyright (c) 2015 Spring, Inc. 4 5 // Permission is hereby granted, free of charge, to any person obtaining a copy 6 // of this software and associated documentation files (the "Software"), to deal 7 // in the Software without restriction, including without limitation the rights 8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 // copies of the Software, and to permit persons to whom the Software is 10 // furnished to do so, subject to the following conditions: 11 12 // The above copyright notice and this permission notice shall be included in 13 // all copies or substantial portions of the Software. 14 15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 // THE SOFTWARE. 22 23 // - Based on https://yougam/libraries/oguzbilgic/fpd, which has the following license: 24 // """ 25 // The MIT License (MIT) 26 27 // Copyright (c) 2013 Oguz Bilgic 28 29 // Permission is hereby granted, free of charge, to any person obtaining a copy of 30 // this software and associated documentation files (the "Software"), to deal in 31 // the Software without restriction, including without limitation the rights to 32 // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 33 // the Software, and to permit persons to whom the Software is furnished to do so, 34 // subject to the following conditions: 35 36 // The above copyright notice and this permission notice shall be included in all 37 // copies or substantial portions of the Software. 38 39 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 40 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 41 // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 42 // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 43 // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 44 // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 45 // """ 46 47 // Copyright 2015 PingCAP, Inc. 48 // 49 // Licensed under the Apache License, Version 2.0 (the "License"); 50 // you may not use this file except in compliance with the License. 51 // You may obtain a copy of the License at 52 // 53 // http://www.apache.org/licenses/LICENSE-2.0 54 // 55 // Unless required by applicable law or agreed to in writing, software 56 // distributed under the License is distributed on an "AS IS" BASIS, 57 // See the License for the specific language governing permissions and 58 // limitations under the License. 59 60 package mysql 61 62 // Decimal implements an arbitrary precision fixed-point decimal. 63 // 64 // To use as part of a struct: 65 // 66 // type Struct struct { 67 // Number Decimal 68 // } 69 // 70 // The zero-value of a Decimal is 0, as you would expect. 71 // 72 // The best way to create a new Decimal is to use decimal.NewFromString, ex: 73 // 74 // n, err := decimal.NewFromString("-123.4567") 75 // n.String() // output: "-123.4567" 76 // 77 // NOTE: this can "only" represent numbers with a maximum of 2^31 digits 78 // after the decimal point. 79 80 import ( 81 "database/sql/driver" 82 "fmt" 83 "math" 84 "math/big" 85 "strconv" 86 "strings" 87 ) 88 89 // DivisionPrecision is the number of decimal places in the result when it 90 // doesn't divide exactly. 91 // 92 // Example: 93 // 94 // d1 := decimal.NewFromFloat(2).Div(decimal.NewFromFloat(3) 95 // d1.String() // output: "0.6667" 96 // d2 := decimal.NewFromFloat(2).Div(decimal.NewFromFloat(30000) 97 // d2.String() // output: "0.0001" 98 // d3 := decimal.NewFromFloat(20000).Div(decimal.NewFromFloat(3) 99 // d3.String() // output: "6666.6666666666666667" 100 // decimal.DivisionPrecision = 3 101 // d4 := decimal.NewFromFloat(2).Div(decimal.NewFromFloat(3) 102 // d4.String() // output: "0.6667" 103 // 104 const ( 105 MaxFractionDigits = 30 106 DivIncreasePrecision = 4 107 ) 108 109 // ZeroDecimal is zero constant, to make computations faster. 110 var ZeroDecimal = NewDecimalFromInt(0, 1) 111 112 var zeroInt = big.NewInt(0) 113 var oneInt = big.NewInt(1) 114 var fiveInt = big.NewInt(5) 115 var tenInt = big.NewInt(10) 116 117 // Decimal represents a fixed-point decimal. It is immutable. 118 // number = value * 10 ^ exp 119 type Decimal struct { 120 value *big.Int 121 122 // this must be an int32, because we cast it to float64 during 123 // calculations. If exp is 64 bit, we might lose precision. 124 // If we cared about being able to represent every possible decimal, we 125 // could make exp a *big.Int but it would hurt performance and numbers 126 // like that are unrealistic. 127 exp int32 128 fracDigits int32 // Number of fractional digits for string result. 129 } 130 131 // ConvertToDecimal converts interface to decimal. 132 func ConvertToDecimal(value interface{}) (Decimal, error) { 133 switch v := value.(type) { 134 case int8: 135 return NewDecimalFromInt(int64(v), 0), nil 136 case int16: 137 return NewDecimalFromInt(int64(v), 0), nil 138 case int32: 139 return NewDecimalFromInt(int64(v), 0), nil 140 case int64: 141 return NewDecimalFromInt(int64(v), 0), nil 142 case int: 143 return NewDecimalFromInt(int64(v), 0), nil 144 case uint8: 145 return NewDecimalFromUint(uint64(v), 0), nil 146 case uint16: 147 return NewDecimalFromUint(uint64(v), 0), nil 148 case uint32: 149 return NewDecimalFromUint(uint64(v), 0), nil 150 case uint64: 151 return NewDecimalFromUint(uint64(v), 0), nil 152 case uint: 153 return NewDecimalFromUint(uint64(v), 0), nil 154 case float32: 155 return NewDecimalFromFloat(float64(v)), nil 156 case float64: 157 return NewDecimalFromFloat(float64(v)), nil 158 case string: 159 return ParseDecimal(v) 160 case Decimal: 161 return v, nil 162 case Hex: 163 return NewDecimalFromInt(int64(v.Value), 0), nil 164 case Bit: 165 return NewDecimalFromUint(uint64(v.Value), 0), nil 166 case Enum: 167 return NewDecimalFromUint(uint64(v.Value), 0), nil 168 case Set: 169 return NewDecimalFromUint(uint64(v.Value), 0), nil 170 default: 171 return Decimal{}, fmt.Errorf("can't convert %v to decimal", value) 172 } 173 } 174 175 // NewDecimalFromInt returns a new fixed-point decimal, value * 10 ^ exp. 176 func NewDecimalFromInt(value int64, exp int32) Decimal { 177 return Decimal{ 178 value: big.NewInt(value), 179 exp: exp, 180 fracDigits: fracDigitsDefault(exp), 181 } 182 } 183 184 // NewDecimalFromUint returns a new fixed-point decimal, value * 10 ^ exp. 185 func NewDecimalFromUint(value uint64, exp int32) Decimal { 186 return Decimal{ 187 value: big.NewInt(0).SetUint64(value), 188 exp: exp, 189 fracDigits: fracDigitsDefault(exp), 190 } 191 } 192 193 // ParseDecimal returns a new Decimal from a string representation. 194 // 195 // Example: 196 // 197 // d, err := ParseDecimal("-123.45") 198 // d2, err := ParseDecimal(".0001") 199 // 200 func ParseDecimal(value string) (Decimal, error) { 201 var intString string 202 var exp = int32(0) 203 204 n := strings.IndexAny(value, "eE") 205 if n > 0 { 206 // It is scientific notation, like 3.14e10 207 expInt, err := strconv.Atoi(value[n+1:]) 208 if err != nil { 209 return Decimal{}, fmt.Errorf("can't convert %s to decimal, incorrect exponent", value) 210 } 211 value = value[0:n] 212 exp = int32(expInt) 213 } 214 215 parts := strings.Split(value, ".") 216 if len(parts) == 1 { 217 // There is no decimal point, we can just parse the original string as 218 // an int. 219 intString = value 220 } else if len(parts) == 2 { 221 intString = parts[0] + parts[1] 222 expInt := -len(parts[1]) 223 exp += int32(expInt) 224 } else { 225 return Decimal{}, fmt.Errorf("can't convert %s to decimal: too many .s", value) 226 } 227 228 dValue := new(big.Int) 229 _, ok := dValue.SetString(intString, 10) 230 if !ok { 231 return Decimal{}, fmt.Errorf("can't convert %s to decimal", value) 232 } 233 234 val := Decimal{ 235 value: dValue, 236 exp: exp, 237 fracDigits: fracDigitsDefault(exp), 238 } 239 if exp < -MaxFractionDigits { 240 val = val.rescale(-MaxFractionDigits) 241 } 242 return val, nil 243 } 244 245 // NewDecimalFromFloat converts a float64 to Decimal. 246 // 247 // Example: 248 // 249 // NewDecimalFromFloat(123.45678901234567).String() // output: "123.4567890123456" 250 // NewDecimalFromFloat(.00000000000000001).String() // output: "0.00000000000000001" 251 // 252 // NOTE: this will panic on NaN, +/-inf. 253 func NewDecimalFromFloat(value float64) Decimal { 254 floor := math.Floor(value) 255 256 // fast path, where float is an int. 257 if floor == value && !math.IsInf(value, 0) { 258 return NewDecimalFromInt(int64(value), 0) 259 } 260 261 str := strconv.FormatFloat(value, 'f', -1, 64) 262 dec, err := ParseDecimal(str) 263 if err != nil { 264 panic(err) 265 } 266 return dec 267 } 268 269 // NewDecimalFromFloatWithExponent converts a float64 to Decimal, with an arbitrary 270 // number of fractional digits. 271 // 272 // Example: 273 // 274 // NewDecimalFromFloatWithExponent(123.456, -2).String() // output: "123.46" 275 // 276 func NewDecimalFromFloatWithExponent(value float64, exp int32) Decimal { 277 mul := math.Pow(10, -float64(exp)) 278 floatValue := value * mul 279 if math.IsNaN(floatValue) || math.IsInf(floatValue, 0) { 280 panic(fmt.Sprintf("Cannot create a Decimal from %v", floatValue)) 281 } 282 dValue := big.NewInt(round(floatValue)) 283 284 return Decimal{ 285 value: dValue, 286 exp: exp, 287 fracDigits: fracDigitsDefault(exp), 288 } 289 } 290 291 // rescale returns a rescaled version of the decimal. Returned 292 // decimal may be less precise if the given exponent is bigger 293 // than the initial exponent of the Decimal. 294 // NOTE: this will truncate, NOT round 295 // 296 // Example: 297 // 298 // d := New(12345, -4) 299 // d2 := d.rescale(-1) 300 // d3 := d2.rescale(-4) 301 // println(d1) 302 // println(d2) 303 // println(d3) 304 // 305 // Output: 306 // 307 // 1.2345 308 // 1.2 309 // 1.2000 310 // 311 func (d Decimal) rescale(exp int32) Decimal { 312 d.ensureInitialized() 313 if exp < -MaxFractionDigits-1 { 314 // Limit the number of digits but we can not call Round here because it is called by Round. 315 // Limit it to MaxFractionDigits + 1 to make sure the final result is correct. 316 exp = -MaxFractionDigits - 1 317 } 318 // Must convert exps to float64 before - to prevent overflow. 319 diff := math.Abs(float64(exp) - float64(d.exp)) 320 value := new(big.Int).Set(d.value) 321 322 expScale := new(big.Int).Exp(tenInt, big.NewInt(int64(diff)), nil) 323 if exp > d.exp { 324 value = value.Quo(value, expScale) 325 } else if exp < d.exp { 326 value = value.Mul(value, expScale) 327 } 328 return Decimal{ 329 value: value, 330 exp: exp, 331 fracDigits: d.fracDigits, 332 } 333 } 334 335 // Abs returns the absolute value of the decimal. 336 func (d Decimal) Abs() Decimal { 337 d.ensureInitialized() 338 d2Value := new(big.Int).Abs(d.value) 339 return Decimal{ 340 value: d2Value, 341 exp: d.exp, 342 fracDigits: d.fracDigits, 343 } 344 } 345 346 // Add returns d + d2. 347 func (d Decimal) Add(d2 Decimal) Decimal { 348 baseExp := min(d.exp, d2.exp) 349 rd := d.rescale(baseExp) 350 rd2 := d2.rescale(baseExp) 351 352 d3Value := new(big.Int).Add(rd.value, rd2.value) 353 return Decimal{ 354 value: d3Value, 355 exp: baseExp, 356 fracDigits: fracDigitsPlus(d.fracDigits, d2.fracDigits), 357 } 358 } 359 360 // Sub returns d - d2. 361 func (d Decimal) Sub(d2 Decimal) Decimal { 362 baseExp := min(d.exp, d2.exp) 363 rd := d.rescale(baseExp) 364 rd2 := d2.rescale(baseExp) 365 366 d3Value := new(big.Int).Sub(rd.value, rd2.value) 367 return Decimal{ 368 value: d3Value, 369 exp: baseExp, 370 fracDigits: fracDigitsPlus(d.fracDigits, d2.fracDigits), 371 } 372 } 373 374 // Mul returns d * d2. 375 func (d Decimal) Mul(d2 Decimal) Decimal { 376 d.ensureInitialized() 377 d2.ensureInitialized() 378 379 expInt64 := int64(d.exp) + int64(d2.exp) 380 if expInt64 > math.MaxInt32 || expInt64 < math.MinInt32 { 381 // It is better to panic than to give incorrect results, as 382 // decimals are usually used for money. 383 panic(fmt.Sprintf("exponent %v overflows an int32!", expInt64)) 384 } 385 386 d3Value := new(big.Int).Mul(d.value, d2.value) 387 val := Decimal{ 388 value: d3Value, 389 exp: int32(expInt64), 390 fracDigits: fracDigitsMul(d.fracDigits, d2.fracDigits), 391 } 392 if val.exp < -(MaxFractionDigits) { 393 val = val.Round(MaxFractionDigits) 394 } 395 return val 396 } 397 398 // Div returns d / d2. If it doesn't divide exactly, the result will have 399 // DivisionPrecision digits after the decimal point. 400 func (d Decimal) Div(d2 Decimal) Decimal { 401 // Division is hard, use Rat to do it. 402 ratNum := d.Rat() 403 ratDenom := d2.Rat() 404 405 quoRat := big.NewRat(0, 1).Quo(ratNum, ratDenom) 406 407 // Converting from Rat to Decimal inefficiently for now. 408 ret, err := ParseDecimal(quoRat.FloatString(MaxFractionDigits + 1)) 409 if err != nil { 410 panic(err) // This should never happen. 411 } 412 // To pass test "2 / 3 * 3 < 2" -> "1". 413 ret = ret.Truncate(MaxFractionDigits) 414 ret.fracDigits = fracDigitsDiv(d.fracDigits) 415 return ret 416 } 417 418 // Cmp compares the numbers represented by d and d2, and returns: 419 // 420 // -1 if d < d2 421 // 0 if d == d2 422 // +1 if d > d2 423 // 424 func (d Decimal) Cmp(d2 Decimal) int { 425 baseExp := min(d.exp, d2.exp) 426 rd := d.rescale(baseExp) 427 rd2 := d2.rescale(baseExp) 428 429 return rd.value.Cmp(rd2.value) 430 } 431 432 // Equals returns whether the numbers represented by d and d2 are equal. 433 func (d Decimal) Equals(d2 Decimal) bool { 434 return d.Cmp(d2) == 0 435 } 436 437 // Exponent returns the exponent, or scale component of the decimal. 438 func (d Decimal) Exponent() int32 { 439 return d.exp 440 } 441 442 // FracDigits returns the number of fractional digits of the decimal. 443 func (d Decimal) FracDigits() int32 { 444 return d.fracDigits 445 } 446 447 // IntPart returns the integer component of the decimal. 448 func (d Decimal) IntPart() int64 { 449 scaledD := d.rescale(0) 450 return scaledD.value.Int64() 451 } 452 453 // Rat returns a rational number representation of the decimal. 454 func (d Decimal) Rat() *big.Rat { 455 d.ensureInitialized() 456 if d.exp <= 0 { 457 // It must negate after casting to prevent int32 overflow. 458 denom := new(big.Int).Exp(tenInt, big.NewInt(-int64(d.exp)), nil) 459 return new(big.Rat).SetFrac(d.value, denom) 460 } 461 462 mul := new(big.Int).Exp(tenInt, big.NewInt(int64(d.exp)), nil) 463 num := new(big.Int).Mul(d.value, mul) 464 return new(big.Rat).SetFrac(num, oneInt) 465 } 466 467 // Float64 returns the nearest float64 value for d and a bool indicating 468 // whether f represents d exactly. 469 // For more details, see the documentation for big.Rat.Float64. 470 func (d Decimal) Float64() (f float64, exact bool) { 471 return d.Rat().Float64() 472 } 473 474 // String returns the string representation of the decimal 475 // with the fixed point. 476 // 477 // Example: 478 // 479 // d := New(-12345, -3) 480 // println(d.String()) 481 // 482 // Output: 483 // 484 // -12.345 485 // 486 func (d Decimal) String() string { 487 return d.StringFixed(d.fracDigits) 488 } 489 490 // StringFixed returns a rounded fixed-point string with places digits after 491 // the decimal point. 492 // 493 // Example: 494 // 495 // NewFromFloat(0).StringFixed(2) // output: "0.00" 496 // NewFromFloat(0).StringFixed(0) // output: "0" 497 // NewFromFloat(5.45).StringFixed(0) // output: "5" 498 // NewFromFloat(5.45).StringFixed(1) // output: "5.5" 499 // NewFromFloat(5.45).StringFixed(2) // output: "5.45" 500 // NewFromFloat(5.45).StringFixed(3) // output: "5.450" 501 // NewFromFloat(545).StringFixed(-1) // output: "550" 502 // 503 func (d Decimal) StringFixed(places int32) string { 504 rounded := d.Round(places) 505 return rounded.string(false) 506 } 507 508 // Round rounds the decimal to places decimal places. 509 // If places < 0, it will round the integer part to the nearest 10^(-places). 510 // 511 // Example: 512 // 513 // NewFromFloat(5.45).Round(1).String() // output: "5.5" 514 // NewFromFloat(545).Round(-1).String() // output: "550" 515 // 516 func (d Decimal) Round(places int32) Decimal { 517 // Truncate to places + 1. 518 ret := d.rescale(-places - 1) 519 520 // Add sign(d) * 0.5. 521 if ret.value.Sign() < 0 { 522 ret.value.Sub(ret.value, fiveInt) 523 } else { 524 ret.value.Add(ret.value, fiveInt) 525 } 526 527 // Floor for positive numbers, Ceil for negative numbers. 528 _, m := ret.value.DivMod(ret.value, tenInt, new(big.Int)) 529 ret.exp++ 530 if ret.value.Sign() < 0 && m.Cmp(zeroInt) != 0 { 531 ret.value.Add(ret.value, oneInt) 532 } 533 ret.fracDigits = places 534 return ret 535 } 536 537 // Floor returns the nearest integer value less than or equal to d. 538 func (d Decimal) Floor() Decimal { 539 d.ensureInitialized() 540 541 exp := big.NewInt(10) 542 543 // It must negate after casting to prevent int32 overflow. 544 exp.Exp(exp, big.NewInt(-int64(d.exp)), nil) 545 546 z := new(big.Int).Div(d.value, exp) 547 return Decimal{value: z, exp: 0} 548 } 549 550 // Ceil returns the nearest integer value greater than or equal to d. 551 func (d Decimal) Ceil() Decimal { 552 d.ensureInitialized() 553 554 exp := big.NewInt(10) 555 556 // It must negate after casting to prevent int32 overflow. 557 exp.Exp(exp, big.NewInt(-int64(d.exp)), nil) 558 559 z, m := new(big.Int).DivMod(d.value, exp, new(big.Int)) 560 if m.Cmp(zeroInt) != 0 { 561 z.Add(z, oneInt) 562 } 563 return Decimal{value: z, exp: 0} 564 } 565 566 // Truncate truncates off digits from the number, without rounding. 567 // 568 // NOTE: precision is the last digit that will not be truncated (must be >= 0). 569 // 570 // Example: 571 // 572 // decimal.NewFromString("123.456").Truncate(2).String() // "123.45" 573 // 574 func (d Decimal) Truncate(precision int32) Decimal { 575 d.ensureInitialized() 576 if precision >= 0 && -precision > d.exp { 577 d = d.rescale(-precision) 578 } 579 d.fracDigits = precision 580 return d 581 } 582 583 // UnmarshalJSON implements the json.Unmarshaler interface. 584 func (d *Decimal) UnmarshalJSON(decimalBytes []byte) error { 585 str, err := unquoteIfQuoted(decimalBytes) 586 if err != nil { 587 return fmt.Errorf("Error decoding string '%s': %s", decimalBytes, err) 588 } 589 590 decimal, err := ParseDecimal(str) 591 *d = decimal 592 if err != nil { 593 return fmt.Errorf("Error decoding string '%s': %s", str, err) 594 } 595 return nil 596 } 597 598 // MarshalJSON implements the json.Marshaler interface. 599 func (d Decimal) MarshalJSON() ([]byte, error) { 600 str := "\"" + d.String() + "\"" 601 return []byte(str), nil 602 } 603 604 // Scan implements the sql.Scanner interface for database deserialization. 605 func (d *Decimal) Scan(value interface{}) error { 606 str, err := unquoteIfQuoted(value) 607 if err != nil { 608 return err 609 } 610 *d, err = ParseDecimal(str) 611 612 return err 613 } 614 615 // Value implements the driver.Valuer interface for database serialization. 616 func (d Decimal) Value() (driver.Value, error) { 617 return d.String(), nil 618 } 619 620 // BigIntValue returns the *bit.Int value member of decimal. 621 func (d Decimal) BigIntValue() *big.Int { 622 return d.value 623 } 624 625 // UnmarshalText implements the encoding.TextUnmarshaler interface for XML 626 // deserialization. 627 func (d *Decimal) UnmarshalText(text []byte) error { 628 str := string(text) 629 630 dec, err := ParseDecimal(str) 631 *d = dec 632 if err != nil { 633 return fmt.Errorf("Error decoding string '%s': %s", str, err) 634 } 635 636 return nil 637 } 638 639 // MarshalText implements the encoding.TextMarshaler interface for XML 640 // serialization. 641 func (d Decimal) MarshalText() (text []byte, err error) { 642 return []byte(d.String()), nil 643 } 644 645 // StringScaled first scales the decimal then calls .String() on it. 646 // NOTE: buggy, unintuitive, and DEPRECATED! Use StringFixed instead. 647 func (d Decimal) StringScaled(exp int32) string { 648 return d.rescale(exp).String() 649 } 650 651 func (d Decimal) string(trimTrailingZeros bool) string { 652 if d.exp >= 0 { 653 return d.rescale(0).value.String() 654 } 655 656 abs := new(big.Int).Abs(d.value) 657 str := abs.String() 658 659 var intPart, fractionalPart string 660 661 // this cast to int will cause bugs if d.exp == INT_MIN 662 // and you are on a 32-bit machine. Won't fix this super-edge case. 663 dExpInt := int(d.exp) 664 if len(str) > -dExpInt { 665 intPart = str[:len(str)+dExpInt] 666 fractionalPart = str[len(str)+dExpInt:] 667 } else { 668 intPart = "0" 669 670 num0s := -dExpInt - len(str) 671 fractionalPart = strings.Repeat("0", num0s) + str 672 } 673 674 if trimTrailingZeros { 675 i := len(fractionalPart) - 1 676 for ; i >= 0; i-- { 677 if fractionalPart[i] != '0' { 678 break 679 } 680 } 681 fractionalPart = fractionalPart[:i+1] 682 } 683 684 number := intPart 685 if len(fractionalPart) > 0 { 686 number += "." + fractionalPart 687 } 688 689 if d.value.Sign() < 0 { 690 return "-" + number 691 } 692 693 return number 694 } 695 696 func (d *Decimal) ensureInitialized() { 697 if d.value == nil { 698 d.value = new(big.Int) 699 } 700 } 701 702 func min(x, y int32) int32 { 703 if x >= y { 704 return y 705 } 706 return x 707 } 708 709 func max(x, y int32) int32 { 710 if x >= y { 711 return x 712 } 713 return y 714 } 715 716 func round(n float64) int64 { 717 if n < 0 { 718 return int64(n - 0.5) 719 } 720 return int64(n + 0.5) 721 } 722 723 func unquoteIfQuoted(value interface{}) (string, error) { 724 bytes, ok := value.([]byte) 725 if !ok { 726 return "", fmt.Errorf("Could not convert value '%+v' to byte array", 727 value) 728 } 729 730 // If the amount is quoted, strip the quotes. 731 if len(bytes) > 2 && bytes[0] == '"' && bytes[len(bytes)-1] == '"' { 732 bytes = bytes[1 : len(bytes)-1] 733 } 734 return string(bytes), nil 735 } 736 737 func fracDigitsDefault(exp int32) int32 { 738 if exp < 0 { 739 return min(MaxFractionDigits, -exp) 740 } 741 742 return 0 743 } 744 745 func fracDigitsPlus(x, y int32) int32 { 746 return max(x, y) 747 } 748 749 func fracDigitsDiv(x int32) int32 { 750 return min(x+DivIncreasePrecision, MaxFractionDigits) 751 } 752 753 func fracDigitsMul(a, b int32) int32 { 754 return min(MaxFractionDigits, a+b) 755 }