mirror of
https://github.com/shopspring/decimal.git
synced 2024-11-22 20:40:48 +01:00
Make NewFromFloat respect the precision of the input (#100)
* Make NewFromFloat respect the precision of the input Restores the previous behaviour where input converted from float is truncated at the precision of the float. The precision is depending on the actual value. Simply making it 15 digits would make it faster, but would in some cases lose some precision. So the code from the stdlib that does this calculation (very well) has been included. Lots of good articles here: https://www.exploringbinary.com/decimal-precision-of-binary-floating-point-numbers/ Performance is around the same as the previous string roundtrip since it basically does the same, but allocations are a bit less. `BenchmarkNewFromStringFloat` is the old method, `BenchmarkNewFromFloat` is the new. ``` BenchmarkNewFromFloatWithExponent-8 10000000 260 ns/op 174 B/op 4 allocs/op BenchmarkNewFromFloat-8 2000000 744 ns/op 90 B/op 2 allocs/op BenchmarkNewFromStringFloat-8 2000000 822 ns/op 258 B/op 6 allocs/op ``` * Update Sin/Tan/Cos tests.
This commit is contained in:
parent
7e43aed1c9
commit
cd690d0c9e
4 changed files with 797 additions and 48 deletions
414
decimal-go.go
Normal file
414
decimal-go.go
Normal file
|
@ -0,0 +1,414 @@
|
||||||
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Multiprecision decimal numbers.
|
||||||
|
// For floating-point formatting only; not general purpose.
|
||||||
|
// Only operations are assign and (binary) left/right shift.
|
||||||
|
// Can do binary floating point in multiprecision decimal precisely
|
||||||
|
// because 2 divides 10; cannot do decimal floating point
|
||||||
|
// in multiprecision binary precisely.
|
||||||
|
package decimal
|
||||||
|
|
||||||
|
type decimal struct {
|
||||||
|
d [800]byte // digits, big-endian representation
|
||||||
|
nd int // number of digits used
|
||||||
|
dp int // decimal point
|
||||||
|
neg bool // negative flag
|
||||||
|
trunc bool // discarded nonzero digits beyond d[:nd]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *decimal) String() string {
|
||||||
|
n := 10 + a.nd
|
||||||
|
if a.dp > 0 {
|
||||||
|
n += a.dp
|
||||||
|
}
|
||||||
|
if a.dp < 0 {
|
||||||
|
n += -a.dp
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := make([]byte, n)
|
||||||
|
w := 0
|
||||||
|
switch {
|
||||||
|
case a.nd == 0:
|
||||||
|
return "0"
|
||||||
|
|
||||||
|
case a.dp <= 0:
|
||||||
|
// zeros fill space between decimal point and digits
|
||||||
|
buf[w] = '0'
|
||||||
|
w++
|
||||||
|
buf[w] = '.'
|
||||||
|
w++
|
||||||
|
w += digitZero(buf[w : w+-a.dp])
|
||||||
|
w += copy(buf[w:], a.d[0:a.nd])
|
||||||
|
|
||||||
|
case a.dp < a.nd:
|
||||||
|
// decimal point in middle of digits
|
||||||
|
w += copy(buf[w:], a.d[0:a.dp])
|
||||||
|
buf[w] = '.'
|
||||||
|
w++
|
||||||
|
w += copy(buf[w:], a.d[a.dp:a.nd])
|
||||||
|
|
||||||
|
default:
|
||||||
|
// zeros fill space between digits and decimal point
|
||||||
|
w += copy(buf[w:], a.d[0:a.nd])
|
||||||
|
w += digitZero(buf[w : w+a.dp-a.nd])
|
||||||
|
}
|
||||||
|
return string(buf[0:w])
|
||||||
|
}
|
||||||
|
|
||||||
|
func digitZero(dst []byte) int {
|
||||||
|
for i := range dst {
|
||||||
|
dst[i] = '0'
|
||||||
|
}
|
||||||
|
return len(dst)
|
||||||
|
}
|
||||||
|
|
||||||
|
// trim trailing zeros from number.
|
||||||
|
// (They are meaningless; the decimal point is tracked
|
||||||
|
// independent of the number of digits.)
|
||||||
|
func trim(a *decimal) {
|
||||||
|
for a.nd > 0 && a.d[a.nd-1] == '0' {
|
||||||
|
a.nd--
|
||||||
|
}
|
||||||
|
if a.nd == 0 {
|
||||||
|
a.dp = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assign v to a.
|
||||||
|
func (a *decimal) Assign(v uint64) {
|
||||||
|
var buf [24]byte
|
||||||
|
|
||||||
|
// Write reversed decimal in buf.
|
||||||
|
n := 0
|
||||||
|
for v > 0 {
|
||||||
|
v1 := v / 10
|
||||||
|
v -= 10 * v1
|
||||||
|
buf[n] = byte(v + '0')
|
||||||
|
n++
|
||||||
|
v = v1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reverse again to produce forward decimal in a.d.
|
||||||
|
a.nd = 0
|
||||||
|
for n--; n >= 0; n-- {
|
||||||
|
a.d[a.nd] = buf[n]
|
||||||
|
a.nd++
|
||||||
|
}
|
||||||
|
a.dp = a.nd
|
||||||
|
trim(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Maximum shift that we can do in one pass without overflow.
|
||||||
|
// A uint has 32 or 64 bits, and we have to be able to accommodate 9<<k.
|
||||||
|
const uintSize = 32 << (^uint(0) >> 63)
|
||||||
|
const maxShift = uintSize - 4
|
||||||
|
|
||||||
|
// Binary shift right (/ 2) by k bits. k <= maxShift to avoid overflow.
|
||||||
|
func rightShift(a *decimal, k uint) {
|
||||||
|
r := 0 // read pointer
|
||||||
|
w := 0 // write pointer
|
||||||
|
|
||||||
|
// Pick up enough leading digits to cover first shift.
|
||||||
|
var n uint
|
||||||
|
for ; n>>k == 0; r++ {
|
||||||
|
if r >= a.nd {
|
||||||
|
if n == 0 {
|
||||||
|
// a == 0; shouldn't get here, but handle anyway.
|
||||||
|
a.nd = 0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for n>>k == 0 {
|
||||||
|
n = n * 10
|
||||||
|
r++
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
c := uint(a.d[r])
|
||||||
|
n = n*10 + c - '0'
|
||||||
|
}
|
||||||
|
a.dp -= r - 1
|
||||||
|
|
||||||
|
var mask uint = (1 << k) - 1
|
||||||
|
|
||||||
|
// Pick up a digit, put down a digit.
|
||||||
|
for ; r < a.nd; r++ {
|
||||||
|
c := uint(a.d[r])
|
||||||
|
dig := n >> k
|
||||||
|
n &= mask
|
||||||
|
a.d[w] = byte(dig + '0')
|
||||||
|
w++
|
||||||
|
n = n*10 + c - '0'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put down extra digits.
|
||||||
|
for n > 0 {
|
||||||
|
dig := n >> k
|
||||||
|
n &= mask
|
||||||
|
if w < len(a.d) {
|
||||||
|
a.d[w] = byte(dig + '0')
|
||||||
|
w++
|
||||||
|
} else if dig > 0 {
|
||||||
|
a.trunc = true
|
||||||
|
}
|
||||||
|
n = n * 10
|
||||||
|
}
|
||||||
|
|
||||||
|
a.nd = w
|
||||||
|
trim(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cheat sheet for left shift: table indexed by shift count giving
|
||||||
|
// number of new digits that will be introduced by that shift.
|
||||||
|
//
|
||||||
|
// For example, leftcheats[4] = {2, "625"}. That means that
|
||||||
|
// if we are shifting by 4 (multiplying by 16), it will add 2 digits
|
||||||
|
// when the string prefix is "625" through "999", and one fewer digit
|
||||||
|
// if the string prefix is "000" through "624".
|
||||||
|
//
|
||||||
|
// Credit for this trick goes to Ken.
|
||||||
|
|
||||||
|
type leftCheat struct {
|
||||||
|
delta int // number of new digits
|
||||||
|
cutoff string // minus one digit if original < a.
|
||||||
|
}
|
||||||
|
|
||||||
|
var leftcheats = []leftCheat{
|
||||||
|
// Leading digits of 1/2^i = 5^i.
|
||||||
|
// 5^23 is not an exact 64-bit floating point number,
|
||||||
|
// so have to use bc for the math.
|
||||||
|
// Go up to 60 to be large enough for 32bit and 64bit platforms.
|
||||||
|
/*
|
||||||
|
seq 60 | sed 's/^/5^/' | bc |
|
||||||
|
awk 'BEGIN{ print "\t{ 0, \"\" }," }
|
||||||
|
{
|
||||||
|
log2 = log(2)/log(10)
|
||||||
|
printf("\t{ %d, \"%s\" },\t// * %d\n",
|
||||||
|
int(log2*NR+1), $0, 2**NR)
|
||||||
|
}'
|
||||||
|
*/
|
||||||
|
{0, ""},
|
||||||
|
{1, "5"}, // * 2
|
||||||
|
{1, "25"}, // * 4
|
||||||
|
{1, "125"}, // * 8
|
||||||
|
{2, "625"}, // * 16
|
||||||
|
{2, "3125"}, // * 32
|
||||||
|
{2, "15625"}, // * 64
|
||||||
|
{3, "78125"}, // * 128
|
||||||
|
{3, "390625"}, // * 256
|
||||||
|
{3, "1953125"}, // * 512
|
||||||
|
{4, "9765625"}, // * 1024
|
||||||
|
{4, "48828125"}, // * 2048
|
||||||
|
{4, "244140625"}, // * 4096
|
||||||
|
{4, "1220703125"}, // * 8192
|
||||||
|
{5, "6103515625"}, // * 16384
|
||||||
|
{5, "30517578125"}, // * 32768
|
||||||
|
{5, "152587890625"}, // * 65536
|
||||||
|
{6, "762939453125"}, // * 131072
|
||||||
|
{6, "3814697265625"}, // * 262144
|
||||||
|
{6, "19073486328125"}, // * 524288
|
||||||
|
{7, "95367431640625"}, // * 1048576
|
||||||
|
{7, "476837158203125"}, // * 2097152
|
||||||
|
{7, "2384185791015625"}, // * 4194304
|
||||||
|
{7, "11920928955078125"}, // * 8388608
|
||||||
|
{8, "59604644775390625"}, // * 16777216
|
||||||
|
{8, "298023223876953125"}, // * 33554432
|
||||||
|
{8, "1490116119384765625"}, // * 67108864
|
||||||
|
{9, "7450580596923828125"}, // * 134217728
|
||||||
|
{9, "37252902984619140625"}, // * 268435456
|
||||||
|
{9, "186264514923095703125"}, // * 536870912
|
||||||
|
{10, "931322574615478515625"}, // * 1073741824
|
||||||
|
{10, "4656612873077392578125"}, // * 2147483648
|
||||||
|
{10, "23283064365386962890625"}, // * 4294967296
|
||||||
|
{10, "116415321826934814453125"}, // * 8589934592
|
||||||
|
{11, "582076609134674072265625"}, // * 17179869184
|
||||||
|
{11, "2910383045673370361328125"}, // * 34359738368
|
||||||
|
{11, "14551915228366851806640625"}, // * 68719476736
|
||||||
|
{12, "72759576141834259033203125"}, // * 137438953472
|
||||||
|
{12, "363797880709171295166015625"}, // * 274877906944
|
||||||
|
{12, "1818989403545856475830078125"}, // * 549755813888
|
||||||
|
{13, "9094947017729282379150390625"}, // * 1099511627776
|
||||||
|
{13, "45474735088646411895751953125"}, // * 2199023255552
|
||||||
|
{13, "227373675443232059478759765625"}, // * 4398046511104
|
||||||
|
{13, "1136868377216160297393798828125"}, // * 8796093022208
|
||||||
|
{14, "5684341886080801486968994140625"}, // * 17592186044416
|
||||||
|
{14, "28421709430404007434844970703125"}, // * 35184372088832
|
||||||
|
{14, "142108547152020037174224853515625"}, // * 70368744177664
|
||||||
|
{15, "710542735760100185871124267578125"}, // * 140737488355328
|
||||||
|
{15, "3552713678800500929355621337890625"}, // * 281474976710656
|
||||||
|
{15, "17763568394002504646778106689453125"}, // * 562949953421312
|
||||||
|
{16, "88817841970012523233890533447265625"}, // * 1125899906842624
|
||||||
|
{16, "444089209850062616169452667236328125"}, // * 2251799813685248
|
||||||
|
{16, "2220446049250313080847263336181640625"}, // * 4503599627370496
|
||||||
|
{16, "11102230246251565404236316680908203125"}, // * 9007199254740992
|
||||||
|
{17, "55511151231257827021181583404541015625"}, // * 18014398509481984
|
||||||
|
{17, "277555756156289135105907917022705078125"}, // * 36028797018963968
|
||||||
|
{17, "1387778780781445675529539585113525390625"}, // * 72057594037927936
|
||||||
|
{18, "6938893903907228377647697925567626953125"}, // * 144115188075855872
|
||||||
|
{18, "34694469519536141888238489627838134765625"}, // * 288230376151711744
|
||||||
|
{18, "173472347597680709441192448139190673828125"}, // * 576460752303423488
|
||||||
|
{19, "867361737988403547205962240695953369140625"}, // * 1152921504606846976
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is the leading prefix of b lexicographically less than s?
|
||||||
|
func prefixIsLessThan(b []byte, s string) bool {
|
||||||
|
for i := 0; i < len(s); i++ {
|
||||||
|
if i >= len(b) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if b[i] != s[i] {
|
||||||
|
return b[i] < s[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Binary shift left (* 2) by k bits. k <= maxShift to avoid overflow.
|
||||||
|
func leftShift(a *decimal, k uint) {
|
||||||
|
delta := leftcheats[k].delta
|
||||||
|
if prefixIsLessThan(a.d[0:a.nd], leftcheats[k].cutoff) {
|
||||||
|
delta--
|
||||||
|
}
|
||||||
|
|
||||||
|
r := a.nd // read index
|
||||||
|
w := a.nd + delta // write index
|
||||||
|
|
||||||
|
// Pick up a digit, put down a digit.
|
||||||
|
var n uint
|
||||||
|
for r--; r >= 0; r-- {
|
||||||
|
n += (uint(a.d[r]) - '0') << k
|
||||||
|
quo := n / 10
|
||||||
|
rem := n - 10*quo
|
||||||
|
w--
|
||||||
|
if w < len(a.d) {
|
||||||
|
a.d[w] = byte(rem + '0')
|
||||||
|
} else if rem != 0 {
|
||||||
|
a.trunc = true
|
||||||
|
}
|
||||||
|
n = quo
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put down extra digits.
|
||||||
|
for n > 0 {
|
||||||
|
quo := n / 10
|
||||||
|
rem := n - 10*quo
|
||||||
|
w--
|
||||||
|
if w < len(a.d) {
|
||||||
|
a.d[w] = byte(rem + '0')
|
||||||
|
} else if rem != 0 {
|
||||||
|
a.trunc = true
|
||||||
|
}
|
||||||
|
n = quo
|
||||||
|
}
|
||||||
|
|
||||||
|
a.nd += delta
|
||||||
|
if a.nd >= len(a.d) {
|
||||||
|
a.nd = len(a.d)
|
||||||
|
}
|
||||||
|
a.dp += delta
|
||||||
|
trim(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Binary shift left (k > 0) or right (k < 0).
|
||||||
|
func (a *decimal) Shift(k int) {
|
||||||
|
switch {
|
||||||
|
case a.nd == 0:
|
||||||
|
// nothing to do: a == 0
|
||||||
|
case k > 0:
|
||||||
|
for k > maxShift {
|
||||||
|
leftShift(a, maxShift)
|
||||||
|
k -= maxShift
|
||||||
|
}
|
||||||
|
leftShift(a, uint(k))
|
||||||
|
case k < 0:
|
||||||
|
for k < -maxShift {
|
||||||
|
rightShift(a, maxShift)
|
||||||
|
k += maxShift
|
||||||
|
}
|
||||||
|
rightShift(a, uint(-k))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we chop a at nd digits, should we round up?
|
||||||
|
func shouldRoundUp(a *decimal, nd int) bool {
|
||||||
|
if nd < 0 || nd >= a.nd {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if a.d[nd] == '5' && nd+1 == a.nd { // exactly halfway - round to even
|
||||||
|
// if we truncated, a little higher than what's recorded - always round up
|
||||||
|
if a.trunc {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return nd > 0 && (a.d[nd-1]-'0')%2 != 0
|
||||||
|
}
|
||||||
|
// not halfway - digit tells all
|
||||||
|
return a.d[nd] >= '5'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Round a to nd digits (or fewer).
|
||||||
|
// If nd is zero, it means we're rounding
|
||||||
|
// just to the left of the digits, as in
|
||||||
|
// 0.09 -> 0.1.
|
||||||
|
func (a *decimal) Round(nd int) {
|
||||||
|
if nd < 0 || nd >= a.nd {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if shouldRoundUp(a, nd) {
|
||||||
|
a.RoundUp(nd)
|
||||||
|
} else {
|
||||||
|
a.RoundDown(nd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Round a down to nd digits (or fewer).
|
||||||
|
func (a *decimal) RoundDown(nd int) {
|
||||||
|
if nd < 0 || nd >= a.nd {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
a.nd = nd
|
||||||
|
trim(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Round a up to nd digits (or fewer).
|
||||||
|
func (a *decimal) RoundUp(nd int) {
|
||||||
|
if nd < 0 || nd >= a.nd {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// round up
|
||||||
|
for i := nd - 1; i >= 0; i-- {
|
||||||
|
c := a.d[i]
|
||||||
|
if c < '9' { // can stop after this digit
|
||||||
|
a.d[i]++
|
||||||
|
a.nd = i + 1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Number is all 9s.
|
||||||
|
// Change to single 1 with adjusted decimal point.
|
||||||
|
a.d[0] = '1'
|
||||||
|
a.nd = 1
|
||||||
|
a.dp++
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract integer part, rounded appropriately.
|
||||||
|
// No guarantees about overflow.
|
||||||
|
func (a *decimal) RoundedInteger() uint64 {
|
||||||
|
if a.dp > 20 {
|
||||||
|
return 0xFFFFFFFFFFFFFFFF
|
||||||
|
}
|
||||||
|
var i int
|
||||||
|
n := uint64(0)
|
||||||
|
for i = 0; i < a.dp && i < a.nd; i++ {
|
||||||
|
n = n*10 + uint64(a.d[i]-'0')
|
||||||
|
}
|
||||||
|
for ; i < a.dp; i++ {
|
||||||
|
n *= 10
|
||||||
|
}
|
||||||
|
if shouldRoundUp(a, a.dp) {
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
81
decimal.go
81
decimal.go
|
@ -171,17 +171,84 @@ func RequireFromString(value string) Decimal {
|
||||||
|
|
||||||
// NewFromFloat converts a float64 to Decimal.
|
// NewFromFloat converts a float64 to Decimal.
|
||||||
//
|
//
|
||||||
// Example:
|
// The converted number will contain the number of significant digits that can be
|
||||||
|
// represented in a float with reliable roundtrip.
|
||||||
|
// This is typically 15 digits, but may be more in some cases.
|
||||||
|
// See https://www.exploringbinary.com/decimal-precision-of-binary-floating-point-numbers/ for more information.
|
||||||
//
|
//
|
||||||
// NewFromFloat(123.45678901234567).String() // output: "123.4567890123456"
|
// For slightly faster conversion, use NewFromFloatWithExponent where you can specify the precision in absolute terms.
|
||||||
// NewFromFloat(.00000000000000001).String() // output: "0.00000000000000001"
|
|
||||||
//
|
|
||||||
// NOTE: some float64 numbers can take up about 300 bytes of memory in decimal representation.
|
|
||||||
// Consider using NewFromFloatWithExponent if space is more important than precision.
|
|
||||||
//
|
//
|
||||||
// NOTE: this will panic on NaN, +/-inf
|
// NOTE: this will panic on NaN, +/-inf
|
||||||
func NewFromFloat(value float64) Decimal {
|
func NewFromFloat(value float64) Decimal {
|
||||||
return NewFromFloatWithExponent(value, math.MinInt32)
|
if value == 0 {
|
||||||
|
return New(0, 0)
|
||||||
|
}
|
||||||
|
return newFromFloat(value, math.Float64bits(value), &float64info)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFromFloat converts a float32 to Decimal.
|
||||||
|
//
|
||||||
|
// The converted number will contain the number of significant digits that can be
|
||||||
|
// represented in a float with reliable roundtrip.
|
||||||
|
// This is typically 6-8 digits depending on the input.
|
||||||
|
// See https://www.exploringbinary.com/decimal-precision-of-binary-floating-point-numbers/ for more information.
|
||||||
|
//
|
||||||
|
// For slightly faster conversion, use NewFromFloatWithExponent where you can specify the precision in absolute terms.
|
||||||
|
//
|
||||||
|
// NOTE: this will panic on NaN, +/-inf
|
||||||
|
func NewFromFloat32(value float32) Decimal {
|
||||||
|
if value == 0 {
|
||||||
|
return New(0, 0)
|
||||||
|
}
|
||||||
|
// XOR is workaround for https://github.com/golang/go/issues/26285
|
||||||
|
a := math.Float32bits(value) ^ 0x80808080
|
||||||
|
return newFromFloat(float64(value), uint64(a)^0x80808080, &float32info)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newFromFloat(val float64, bits uint64, flt *floatInfo) Decimal {
|
||||||
|
if math.IsNaN(val) || math.IsInf(val, 0) {
|
||||||
|
panic(fmt.Sprintf("Cannot create a Decimal from %v", val))
|
||||||
|
}
|
||||||
|
exp := int(bits>>flt.mantbits) & (1<<flt.expbits - 1)
|
||||||
|
mant := bits & (uint64(1)<<flt.mantbits - 1)
|
||||||
|
|
||||||
|
switch exp {
|
||||||
|
case 0:
|
||||||
|
// denormalized
|
||||||
|
exp++
|
||||||
|
|
||||||
|
default:
|
||||||
|
// add implicit top bit
|
||||||
|
mant |= uint64(1) << flt.mantbits
|
||||||
|
}
|
||||||
|
exp += flt.bias
|
||||||
|
|
||||||
|
var d decimal
|
||||||
|
d.Assign(mant)
|
||||||
|
d.Shift(exp - int(flt.mantbits))
|
||||||
|
d.neg = bits>>(flt.expbits+flt.mantbits) != 0
|
||||||
|
|
||||||
|
roundShortest(&d, mant, exp, flt)
|
||||||
|
// If less than 19 digits, we can do calculation in an int64.
|
||||||
|
if d.nd < 19 {
|
||||||
|
tmp := int64(0)
|
||||||
|
m := int64(1)
|
||||||
|
for i := d.nd - 1; i >= 0; i-- {
|
||||||
|
tmp += m * int64(d.d[i]-'0')
|
||||||
|
m *= 10
|
||||||
|
}
|
||||||
|
if d.neg {
|
||||||
|
tmp *= -1
|
||||||
|
}
|
||||||
|
return Decimal{value: big.NewInt(tmp), exp: int32(d.dp) - int32(d.nd)}
|
||||||
|
}
|
||||||
|
dValue := new(big.Int)
|
||||||
|
dValue, ok := dValue.SetString(string(d.d[:d.nd]), 10)
|
||||||
|
if ok {
|
||||||
|
return Decimal{value: dValue, exp: int32(d.dp) - int32(d.nd)}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewFromFloatWithExponent(val, int32(d.dp)-int32(d.nd))
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFromFloatWithExponent converts a float64 to Decimal, with an arbitrary
|
// NewFromFloatWithExponent converts a float64 to Decimal, with an arbitrary
|
||||||
|
|
232
decimal_test.go
232
decimal_test.go
|
@ -4,13 +4,16 @@ import (
|
||||||
"database/sql/driver"
|
"database/sql/driver"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"math/rand"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
"testing/quick"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -42,9 +45,19 @@ var testTable = []*testEnt{
|
||||||
{.1000000000000003, "0.1000000000000003", "", "0.1000000000000003000000000000001234123412"},
|
{.1000000000000003, "0.1000000000000003", "", "0.1000000000000003000000000000001234123412"},
|
||||||
{.1000000000000005, "0.1000000000000005", "", "0.1000000000000005000000000000000006441234"},
|
{.1000000000000005, "0.1000000000000005", "", "0.1000000000000005000000000000000006441234"},
|
||||||
{.1000000000000008, "0.1000000000000008", "", "0.100000000000000800000000000000000009999999999999999999999999999"},
|
{.1000000000000008, "0.1000000000000008", "", "0.100000000000000800000000000000000009999999999999999999999999999"},
|
||||||
{1e25, "10000000000000000000000000", "", "10000000000000000000000000.00000000000000000098798978"},
|
{1e25, "10000000000000000000000000", "", ""},
|
||||||
{math.MaxInt64, strconv.FormatInt(math.MaxInt64, 10), "", strconv.FormatInt(math.MaxInt64, 10)},
|
{1.5e14, "150000000000000", "", ""},
|
||||||
{1.29067116156722e-309, "0", "", "0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001290671161567218558822290567835270536800098852722416870074139002112543896676308448335063375297788379444685193974290737962187240854947838776604607190387984577130572928111657710645015086812756013489109884753559084166516937690932698276436869274093950997935137476803610007959500457935217950764794724766740819156974617155861568214427828145972181876775307023388139991104942469299524961281641158436752347582767153796914843896176260096039358494077706152272661453132497761307744086665088096215425146090058519888494342944692629602847826300550628670375451325582843627504604013541465361435761965354140678551369499812124085312128659002910905639984075064968459581691226705666561364681985266583563078466180095375402399087817404368974165082030458595596655868575908243656158447265625000000000000000000000000000000000000004440000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},
|
{1.5e15, "1500000000000000", "", ""},
|
||||||
|
{1.5e16, "15000000000000000", "", ""},
|
||||||
|
{1.0001e25, "10001000000000000000000000", "", ""},
|
||||||
|
{1.0001000000000000033e25, "10001000000000000000000000", "", ""},
|
||||||
|
{2e25, "20000000000000000000000000", "", ""},
|
||||||
|
{4e25, "40000000000000000000000000", "", ""},
|
||||||
|
{8e25, "80000000000000000000000000", "", ""},
|
||||||
|
{1e250, "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "", ""},
|
||||||
|
{2e250, "20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "", ""},
|
||||||
|
{math.MaxInt64, strconv.FormatFloat(float64(math.MaxInt64), 'f', -1, 64), "", strconv.FormatInt(math.MaxInt64, 10)},
|
||||||
|
{1.29067116156722e-309, "0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000129067116156722", "", "0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001290671161567218558822290567835270536800098852722416870074139002112543896676308448335063375297788379444685193974290737962187240854947838776604607190387984577130572928111657710645015086812756013489109884753559084166516937690932698276436869274093950997935137476803610007959500457935217950764794724766740819156974617155861568214427828145972181876775307023388139991104942469299524961281641158436752347582767153796914843896176260096039358494077706152272661453132497761307744086665088096215425146090058519888494342944692629602847826300550628670375451325582843627504604013541465361435761965354140678551369499812124085312128659002910905639984075064968459581691226705666561364681985266583563078466180095375402399087817404368974165082030458595596655868575908243656158447265625000000000000000000000000000000000000004440000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
}
|
}
|
||||||
|
|
||||||
var testTableScientificNotation = map[string]string{
|
var testTableScientificNotation = map[string]string{
|
||||||
|
@ -89,11 +102,11 @@ func init() {
|
||||||
|
|
||||||
func TestNewFromFloat(t *testing.T) {
|
func TestNewFromFloat(t *testing.T) {
|
||||||
for _, x := range testTable {
|
for _, x := range testTable {
|
||||||
s := x.exact
|
s := x.short
|
||||||
d := NewFromFloat(x.float)
|
d := NewFromFloat(x.float)
|
||||||
if d.String() != s {
|
if d.String() != s {
|
||||||
t.Errorf("expected %s, got %s (%s, %d)",
|
t.Errorf("expected %s, got %s (float: %v) (%s, %d)",
|
||||||
s, d.String(),
|
s, d.String(), x.float,
|
||||||
d.value.String(), d.exp)
|
d.value.String(), d.exp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -112,6 +125,121 @@ func TestNewFromFloat(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNewFromFloatRandom(t *testing.T) {
|
||||||
|
n := 0
|
||||||
|
rng := rand.New(rand.NewSource(0xdead1337))
|
||||||
|
for {
|
||||||
|
n++
|
||||||
|
if n == 10 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
in := (rng.Float64() - 0.5) * math.MaxFloat64 * 2
|
||||||
|
want, err := NewFromString(strconv.FormatFloat(in, 'f', -1, 64))
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
got := NewFromFloat(in)
|
||||||
|
if !want.Equal(got) {
|
||||||
|
t.Errorf("in: %v, expected %s (%s, %d), got %s (%s, %d) ",
|
||||||
|
in, want.String(), want.value.String(), want.exp,
|
||||||
|
got.String(), got.value.String(), got.exp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewFromFloatQuick(t *testing.T) {
|
||||||
|
err := quick.Check(func(f float64) bool {
|
||||||
|
want, werr := NewFromString(strconv.FormatFloat(f, 'f', -1, 64))
|
||||||
|
if werr != nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
got := NewFromFloat(f)
|
||||||
|
return got.Equal(want)
|
||||||
|
}, &quick.Config{})
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewFromFloat32Random(t *testing.T) {
|
||||||
|
n := 0
|
||||||
|
rng := rand.New(rand.NewSource(0xdead1337))
|
||||||
|
for {
|
||||||
|
n++
|
||||||
|
if n == 10 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
in := float32((rng.Float64() - 0.5) * math.MaxFloat32 * 2)
|
||||||
|
want, err := NewFromString(strconv.FormatFloat(float64(in), 'f', -1, 32))
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
got := NewFromFloat32(in)
|
||||||
|
if !want.Equal(got) {
|
||||||
|
t.Errorf("in: %v, expected %s (%s, %d), got %s (%s, %d) ",
|
||||||
|
in, want.String(), want.value.String(), want.exp,
|
||||||
|
got.String(), got.value.String(), got.exp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewFromFloat32Quick(t *testing.T) {
|
||||||
|
err := quick.Check(func(f float32) bool {
|
||||||
|
want, werr := NewFromString(strconv.FormatFloat(float64(f), 'f', -1, 32))
|
||||||
|
if werr != nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
got := NewFromFloat32(f)
|
||||||
|
return got.Equal(want)
|
||||||
|
}, &quick.Config{})
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkNewFromFloatWithExponent(b *testing.B) {
|
||||||
|
rng := rand.New(rand.NewSource(0xdead1337))
|
||||||
|
in := make([]float64, b.N)
|
||||||
|
for i := range in {
|
||||||
|
in[i] = rng.NormFloat64() * 10e20
|
||||||
|
}
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
in := rng.NormFloat64() * 10e20
|
||||||
|
_ = NewFromFloatWithExponent(in, math.MinInt32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkNewFromFloat(b *testing.B) {
|
||||||
|
rng := rand.New(rand.NewSource(0xdead1337))
|
||||||
|
in := make([]float64, b.N)
|
||||||
|
for i := range in {
|
||||||
|
in[i] = rng.NormFloat64() * 10e20
|
||||||
|
}
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
_ = NewFromFloat(in[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkNewFromStringFloat(b *testing.B) {
|
||||||
|
rng := rand.New(rand.NewSource(0xdead1337))
|
||||||
|
in := make([]float64, b.N)
|
||||||
|
for i := range in {
|
||||||
|
in[i] = rng.NormFloat64() * 10e20
|
||||||
|
}
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
in := strconv.FormatFloat(in[i], 'f', -1, 64)
|
||||||
|
_, _ = NewFromString(in)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestNewFromString(t *testing.T) {
|
func TestNewFromString(t *testing.T) {
|
||||||
for _, x := range testTable {
|
for _, x := range testTable {
|
||||||
s := x.short
|
s := x.short
|
||||||
|
@ -151,6 +279,9 @@ func TestNewFromString(t *testing.T) {
|
||||||
|
|
||||||
func TestFloat64(t *testing.T) {
|
func TestFloat64(t *testing.T) {
|
||||||
for _, x := range testTable {
|
for _, x := range testTable {
|
||||||
|
if x.inexact == "" || x.inexact == "-" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
s := x.exact
|
s := x.exact
|
||||||
d, err := NewFromString(s)
|
d, err := NewFromString(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -2298,18 +2429,18 @@ func TestAtan(t *testing.T) {
|
||||||
"1.0",
|
"1.0",
|
||||||
"5.0",
|
"5.0",
|
||||||
"10",
|
"10",
|
||||||
"11000020.2407442310156021090304691671842603586882014729198302312846062338790031898128063403419218957424",
|
"11000020.2407442310156021090304691671842603586882014729198302312846062338790031898128063403419218957424",
|
||||||
}
|
}
|
||||||
sols := []string{
|
sols := []string{
|
||||||
"-1.2407643882205801102743706275310603586882014729198302312846062338790031898128063403419218957424163818359375",
|
"-1.24076438822058001027437062753106",
|
||||||
"-0.78539816339744833061616997868383017934410073645991511564230311693950159490640317017096094787120819091796875",
|
"-0.78539816339744833061616997868383",
|
||||||
"-0.24497866312686415",
|
"-0.24497866312686415",
|
||||||
"0.0",
|
"0.0",
|
||||||
"0.318747560420644443",
|
"0.318747560420644443",
|
||||||
"0.78539816339744833061616997868383017934410073645991511564230311693950159490640317017096094787120819091796875",
|
"0.78539816339744833061616997868383",
|
||||||
"1.3734007669450159012323399573676603586882014729198302312846062338790031898128063403419218957424163818359375",
|
"1.37340076694501580123233995736766",
|
||||||
"1.4711276743037346312323399573676603586882014729198302312846062338790031898128063403419218957424163818359375",
|
"1.47112767430373453123233995736766",
|
||||||
"1.5707962358859730612325945023537403586882014729198302312846062338790031898128063403419218957424163818359375",
|
"1.57079623588597296123259450235374",
|
||||||
}
|
}
|
||||||
for i, inp := range inps {
|
for i, inp := range inps {
|
||||||
d, err := NewFromString(inp)
|
d, err := NewFromString(inp)
|
||||||
|
@ -2338,18 +2469,17 @@ func TestSin(t *testing.T) {
|
||||||
"1.0",
|
"1.0",
|
||||||
"5.0",
|
"5.0",
|
||||||
"10",
|
"10",
|
||||||
"11000020.2407442310156021090304691671842603586882014729198302312846062338790031898128063403419218957424",
|
"11000020.2407442310156021090304691671842603586882014729198302312846062338790031898128063403419218957424",
|
||||||
}
|
}
|
||||||
sols := []string{
|
sols := []string{"-0.22057186252002995641471297726318877448242875710373383657841216606788849153474483300147427943530288911869356126149550184271061369789963810497434594683859566879253561990821788142048867910104964466745284318577343435957806286762494529983369776697504436326725441516925396488258485248699247367113416543705253919473126183478178486954138205996912770183192357029798618739277146694040778731661407420114923656224752540889120768",
|
||||||
"-0.220571862520030093613839729898389234591448264443828979962999436149729548845614563657783710150808249493659603883785557750857064742068654401611592366453156979425089038732558977915147138610177101332138819745624841999009731533470874398791630404814623756725761484209848526893621903868344844362592350061614721709283168025028307789990557501123216276655612701350632840149744527732872833304632776220881820168763715880072271900752263175824768749676997835634284780882959485313122780499486873741058283218325040301421620652217699025347852371634749059985101913743575566482455108757945784327770283152556778940395109157571785095552777237471737930299497127855782791647416409676751196562400230573256919649166116220548146722732673811940013822174052471575484241086300786209457059067702404625074214637302180559257156598478224357461349695824437855046828206155188482292930722180491096361781653423287753045189099820938975700063357767823639345982521057442719437079960883170296730778877529726323641962581167118741985973085143794261349309399843621404104514700512532703761239968546841161640494797236796414402075947283426422877298624337798757146020442229118476349906575010431352541089067121029579490866064323880357132858662072455977109093817967157613567800944577216024589669093782841129397681562208313003621389103425798339230823330581188201904296875",
|
"-0.841470984807896544828551915928318375739843472469519282898610111931110319333748010828751784005573402229699531838022117989945539661588502120624574802425114599802714611508860519655182175315926637327774878594985045816542706701485174683683726979309922117859910272413672784175028365607893544855897795184024100973080880074046886009375162838756876336134083638363801171409953672944184918309063800980214873465660723218405962257950683415203634506166523593278",
|
||||||
"-0.84147098480789650683573384227719871264659725213827912307678945963233888758666252541652307542471941569920950873234694687123276222626964952320957348347806244448304658355378064371162688704108432893734339281119107889886243608606771440333499496399246182550579552307436056577989755048676139388257574972355638331020916986327112812449023235994235220681962126402627149122741398037411569225585167209440887381294958909446263040889436515610243685011381400045762457675558838333095494482138227725013381292722259213324814381642325470123171162316406069142833674558352099403808484142312206036567122374357983536120130367436871049536150555321227634134943262101222587962853023526365048081446005272233936756658798560188088496199440605960018665932771208203273875932636591008594752836095901878899636892331191188133444513639520743904232369072391326448163751628578886099960312207261234582748222511007033947148867295201489673608530271710726980420265749989442268185776660104680951516862727780322815011940555693819786827407000470928166813302681223319136916385379500478197064927760223020342764479386095349145229773585152310192696649682836151684354735282894320955021997802761069713870309184654536840910246184967655772931790056052366745119986847633246318705770507591911530119455091063686301656648189606417807689546576464738456252196397075290117772324937902655849801056962584258183367906235526162380299193832940968379238027598232552151102936477400362491607666015625",
|
"-0.2474039592545229296662577977006816864013671875",
|
||||||
"-0.247403959254522929719728461264852108650160857317149198152655832001777826134603088803487480618059635162353515625",
|
"0",
|
||||||
"0.0",
|
"0.3240430283948683457891331120415701894104386268737728",
|
||||||
"0.324043028394868345912501559420824735488967340443112210114701957327566252120565337691004970110952854156494140625",
|
"0.841470984807896544828551915928318375739843472469519282898610111931110319333748010828751784005573402229699531838022117989945539661588502120624574802425114599802714611508860519655182175315926637327774878594985045816542706701485174683683726979309922117859910272413672784175028365607893544855897795184024100973080880074046886009375162838756876336134083638363801171409953672944184918309063800980214873465660723218405962257950683415203634506166523593278",
|
||||||
"0.84147098480789650683573384227719871264659725213827912307678945963233888758666252541652307542471941569920950873234694687123276222626964952320957348347806244448304658355378064371162688704108432893734339281119107889886243608606771440333499496399246182550579552307436056577989755048676139388257574972355638331020916986327112812449023235994235220681962126402627149122741398037411569225585167209440887381294958909446263040889436515610243685011381400045762457675558838333095494482138227725013381292722259213324814381642325470123171162316406069142833674558352099403808484142312206036567122374357983536120130367436871049536150555321227634134943262101222587962853023526365048081446005272233936756658798560188088496199440605960018665932771208203273875932636591008594752836095901878899636892331191188133444513639520743904232369072391326448163751628578886099960312207261234582748222511007033947148867295201489673608530271710726980420265749989442268185776660104680951516862727780322815011940555693819786827407000470928166813302681223319136916385379500478197064927760223020342764479386095349145229773585152310192696649682836151684354735282894320955021997802761069713870309184654536840910246184967655772931790056052366745119986847633246318705770507591911530119455091063686301656648189606417807689546576464738456252196397075290117772324937902655849801056962584258183367906235526162380299193832940968379238027598232552151102936477400362491607666015625",
|
"-0.958924274663138409032065951037351417114444405831206421994322505831797734568720303321152847999323782235893449831846516332891972309733806145798957570823292783131379570446989311599459252931842975162373777189193072018951049969744350662993214861042908755303566670204873618202680865638534865944483058650517380292320436016362659617294570185140789829574277032406195741535138712427510938542219940873171248862329526140744770994303733112530324791184417282382",
|
||||||
"-0.95892427466313846886683534084169138601699178595056142681129038893400410281163045903621198874295374290149806823897075576057724999482959874362888984630786877750800707948164478439888413437709227541296453939066231042449153560817956529124771991719434464325257307490209688817348630841990228088502580219431623697760216390920129365244393334429239217501291865772417470981461975427863913628459487634361457463896191397206119089801538318057594728767278995563353925328463456560840888895608182514323808823801838724482524462741712473496938668730262585034295941891365544300178534659369917661430555201335114597830077556398746790054730682231578093617522006106659977088453875512527401574137870617360741477467052899927465250688663724908651769559466919777914497651416655110015287957761809374118954830175592272643086681859204507636705728518901196924686915642366269243409467335313632803457424138328976320449572075303129501941586734619627126950347146441488301272523732890971103193432131967093584975094064352688636321088866275878367912478080039614015674090467373532503838989934725811696669260106530065305130564789502177378344025691707116401561519233199329283661803416619394138904068356512359009119169667571681552281997620458915816124425995894145459910451225779660911316891499301549117918834162954131295015995478902576153796243561887919093281708146016725119431774666779045011119428333353937254827947830587875729623490751729608660980375134386122226715087890625",
|
"-0.54402111088937016772477554483765124109312606762621462357463994520238396180161585438877562935656067241573063207614488370477645194661241525080677431257416988398683714890165970942834453391033857378247849486306346743023618509617104937236345831462093934032592562972419977883837745736210439651143668255744843041350221801750331646628192115694352540293150183983357476391787825596543270240461102629075832777618592034309799936",
|
||||||
"-0.544021110889369814404798546234261521735237410341301440744913863554325413910729487222404754912397132389280869582562649416317020824255899391102716253549602359933406667420857908751554064982667505778980864397665237869392769251295144996601379178780771501957858736340861984904014191524939793604688756271913886434778180316203812548425041682948461830667971245994025528380063656691687013885731759172341309655658172703937945366976128597657101230629806658897303549468649147494313422814604383947907342285887634159176609268080528703630505118954169027929142559898709956536517735787676487117591429732597764129997800544321069045676840705169697409709450991200259966568075515292000715246707423119024660809599616729869855242609248565503156233847151639381625642548896051440565640966333400046266460293523862957282305141303657282623793830073310394349418290939283661501995774676808852008306303431767521000117474347792119119745767325061425517820206720145795639782171641765977980488850129569363740173287329545019826050789666603219553652178298235868990551128361160456166647394642535572127727629420370720856130359966967599668830582910424823037763854828905673063487188976311335956440851988180468345725600705105113853947651574770698730911647817190648000646872041955859376392859382055300138695355787127336060458870914402496055117808282375335693359375",
|
"-0.564291758480422881634770440632390475980828840253516895637281099241819037882007239070203007530085741820184955492382572029153491807930868879341091067301689987699567034024159005627332722089169680203292567574310010066799858914647295684974242359142300929248173166551428537696685165964880390889406578530338963341989826231514301546476672476399906348023294571001061677668735117509440368611093448917120819545826797975989350435900286332895885871219875665471968941335407351099209738417818747252638912592184093301853338763294381446907254104878969784040526201729163408095795934201105630182851806342356035203279670146684553491616847294749721014579109870396804713831114709372638323643327823671187472335866664108658093206409882794958673673978956925250261545083579947618620746006004554405785185537391110314728988164693223775249484198058394348289545771967707968288542718255197272633789792059019367104377340604030147471453833808674013259696102003732963091159662478879760121731138091114134586544668859915547568540172541576138084166990547345181184322550297604278946942918844039406876827936831612756344331500301118652183156052728447906384772901595431751550607818380262138322673253023464533931883787069611052589166000316238423939491520880451263927981787175602294299295744",
|
||||||
"-0.564291758073920672156060501108780948637502927903402695682970758082173347334144085493099932047342878232107294208163423635351694839181128599190761981992082190183414367145761958978263205360050276797203465120166463337285861568628620441149869080262018002460551105733370384496691552603807079787064355499979892738941692390909198368605275928720995456124329350110140031040327865030504338978174244479702663590952255309812151905391076362043165507118546398673253957125454990703254702293833362635280840010399956637688760201442320428708562854314419339362472820724298986435162931641340060501848890585327411159080467227885852591584159465243368331681937734746160681439404005233844642476786199607795910618003577395193096223575912506207477927572401934790710176468073033112942732454695154492720511230782735184156027155137618173659003878927697237751139877779082916148874086491265428313018347132700490228131397266369640661232003084568637049642401980172435548737268283623715380443755530399410106957744899992161330205161097513785489406292271887390739430612193060474304401657511461250218562733033893187306639264886516827894130028111468708805823753758224864450015655567869605537758979198887215555526950741196023433812962018677695204317878927956155283357420412564940844662156159296973147878187706628631717213628871121500196750275790691375732421875",
|
|
||||||
}
|
}
|
||||||
for i, inp := range inps {
|
for i, inp := range inps {
|
||||||
d, err := NewFromString(inp)
|
d, err := NewFromString(inp)
|
||||||
|
@ -2378,18 +2508,18 @@ func TestCos(t *testing.T) {
|
||||||
"1.0",
|
"1.0",
|
||||||
"5.0",
|
"5.0",
|
||||||
"10",
|
"10",
|
||||||
"11000020.2407442310156021090304691671842603586882014729198302312846062338790031898128063403419218957424",
|
"11000020.2407442310156021090304691671842603586882014729198302312846062338790031898128063403419218957424",
|
||||||
}
|
}
|
||||||
sols := []string{
|
sols := []string{
|
||||||
"-0.975370726167463436728505866323714237868918798735337852490354630275400590397256757982930518671177656988788392411709345759154371178337418085499048191038650091945778580197329516971729513331012900776507504230803826799226710606177535289143559059224362661001603838745169803182674368143452935332062804519861768577138064573259069358975042122485627388192604101700302462362798592115038066626006203292151971117547825788365029212778673068841445412348366566041687247190622871297208478844658065023427261675103854131453079888921085982507674462174796122088474426882259116347806427809304457623578281770915649130727943036401841073052876646614496797452163682420483896962238944883515469778180754205404941121141599952645904787654598990827384683885441411829970587806867632776521257761008506280475694989732289455150722563701599552835784792787892378475275568451704113581492707873602587027241507884412830033365653914549639245334821262039117311046735253960816076120011217151854994903031629514573221302055487026138480621515317251868170670711382669181677841187033304861609062981031260474272177938456322715827189878292157663041430578246790062347759217920400856872733420989333068628730367636465064551304273677450773043171019346261214827671284261815921602597267030573778706635242318228554033918329328451836597811660816887574069149657366695399451977163530476815743551656054860762997757628606444388219917589048259254358441694421344436705112457275390625",
|
"-0.975370726167463467746508538219884948528729295145689640359666742268127382748782064668565276308334226452812521220478854320025773591423493734486361306323829818426063430805234608660356853863442937297855742231573288105774823103008774355455799906250461848079705023428527473474556899228935370709945979509634251305018978306493011197513482210179171510947538040406781879762352211326273272515279567525396877609653501706919545667682725671944948392322552266752",
|
||||||
"0.5403023058681397185594704958555785318789737039530258806063132922287686731767103380722879951346341700301934154242672285869862285136280035256635149087722026456653060623287636554810379311566025776640284286043366692017812351065106848975433243878434601646053373656175870219143335780037780263780528022552589948882631781788387243759097393407418459341665025578959743680402679565710214589639277870162089735459876789876164945626397889278949094061300698882180972876375063478762441763141045691438279791675986386217937407677843979434037325100615614204173839676230023544297002103390623811623287987178412049715000660987495684907814359780765658960715423795658408220614069561530422742718922893554271137549412369147629593458239490366605797325139239944180051692566520667214675204069476110320173267646327440417945329562672924843423546460029298423629611979148079742086487910832189641973781754022003095306885302971446512196936121388134045074972570593581133444925052909080976768554628154520121141808489601642421723177702083881285314379847744230155051966361158007017591582046619808944751148550841102122653076944135728372456492657514171872121435155305860386442665726120257630353953444221670261220705805623292334551636518107895571396829211893470388375917284217734121333575035514871632238034279250742569584498765995392820238318876135963364504277706146240234375",
|
"0.54030230586813965874561515067176071767603141150991567490927772778673118786033739102174242337864109186439207498973007363884202112942385976796862442063752663646870430360736682397798633852405003167527051283327366631405990604840629657123985368031838052877290142895506386796217551784101265975360960112885444847880134909594560331781699767647860744559228420471946006511861233129745921297270844542687374552066388998112901504",
|
||||||
"0.968912421710644784098953478920868172610959295777507211448260716808741793725813506998889579335809685289859771728515625",
|
"0.968912421710644784099084544806854121387004852294921875",
|
||||||
"1.0",
|
"1",
|
||||||
"0.946042343528386971548655274719127421974169853736868957009626534392384054569270779300182994120405055582523345947265625",
|
"0.9460423435283869715490383692051286742343482760977712222",
|
||||||
"0.5403023058681397185594704958555785318789737039530258806063132922287686731767103380722879951346341700301934154242672285869862285136280035256635149087722026456653060623287636554810379311566025776640284286043366692017812351065106848975433243878434601646053373656175870219143335780037780263780528022552589948882631781788387243759097393407418459341665025578959743680402679565710214589639277870162089735459876789876164945626397889278949094061300698882180972876375063478762441763141045691438279791675986386217937407677843979434037325100615614204173839676230023544297002103390623811623287987178412049715000660987495684907814359780765658960715423795658408220614069561530422742718922893554271137549412369147629593458239490366605797325139239944180051692566520667214675204069476110320173267646327440417945329562672924843423546460029298423629611979148079742086487910832189641973781754022003095306885302971446512196936121388134045074972570593581133444925052909080976768554628154520121141808489601642421723177702083881285314379847744230155051966361158007017591582046619808944751148550841102122653076944135728372456492657514171872121435155305860386442665726120257630353953444221670261220705805623292334551636518107895571396829211893470388375917284217734121333575035514871632238034279250742569584498765995392820238318876135963364504277706146240234375",
|
"0.54030230586813965874561515067176071767603141150991567490927772778673118786033739102174242337864109186439207498973007363884202112942385976796862442063752663646870430360736682397798633852405003167527051283327366631405990604840629657123985368031838052877290142895506386796217551784101265975360960112885444847880134909594560331781699767647860744559228420471946006511861233129745921297270844542687374552066388998112901504",
|
||||||
"0.2836621854632262640413454705014792126730041372592792257206146645426601396441260356011571632089582618925838153657699769828738164020634023542401271546832973668591965970780399287846132178786932147719489387057249755694634919271032742386467263343003762216059912285589934893404186137482489686474984451054771103493648603655340770275593072267521598532667125806036270513157359920795997662877180316554125323347714021810156977000099765637673158040510070215919734518464013962899531358902754977185164550708058199871247160015886870149163066556093196783440812874006182781633602366172183573725257608628866745555998550377960547686470245458626674802626292796549871502254193653242073557087898962773658255810053531370802115864997325060870572958692356612208396119690852149106422002310275167937817158288794799498840438933404405058238604063789542363766559068475105058515056790385539505205746157593694133334912162302627008416603294000615739181111749007688625782080015509782711717307370897514073199106746929535880890780214210719294387601483817437596151502942142722181977054762243644235893248214844557965863434535805464134779033144520828071538407409414463996182938827134980848798774952211899634360773590821173224015934994691863733763099257382589344052735164638723090648652823314675360473802118354232333173901927332659182734442282480813446454703807830810546875",
|
"0.28366218546322646623291670213892426815646045792775066552057877370468842342090306560693620285882975471913545189522117672866861003904575909174769890684057564495184019705963607555427518763375472432216131070235796577209064861003009894615394882021220247535890708789312783718414424224334988974848162884228012265684775651099758365989567444515619764427493598258393280941942356912304265535918025036942025858493361644535438208",
|
||||||
"-0.839071529076452452453116298055375283024545196907005751226679269494945423257632785713674884440909521085910953206821682885350514489569383484553680293874464258013074629595233233440423524040185080138431677219644537006650333440982266180848432613265727672098505530500860099490052714852637696219860623419861733967504942346257426883650461547676693756422205686582533132927538864456011428540560137047577109540901355332714454892042154044099772961016405398585134639556422987015399944634792029504830682794892974110049771680445087591216461375304720930330852114906188605879368500242393092090599991056282929140339515922705640197683216586300345608814191348583643897583052496585038234458432300602598656172228800591628810870703061601079842675931288590090649649722933122710180797353905585641576282107791663819561479911160784057959370842865399560455463184561649904326467913053219927760200406450092385176263660350059186320075841952511620387666555291853410264149054381143798602019026379808898830628940629734269442061546806433026794983473131041596411391519359668360706593453379582689919628495055879290310156211842712529358591580000339115277557733264569390191184923563095676385834461753760385376605508361399123052214852866448517012467160704995276728328831739643710159503245565807479821789258404871375420699263398077037976545179716664243275062643380243567701961405078734621807138136709079831010972563517559541512724763379083015024662017822265625",
|
"-0.839071529076452222947082170022504835457755803801719612447629165523199043803440231769716865070163209041973184176293170330332317060558438085478980463542480791358920580076809381102480339018809694514100495572097422057215638383077242523713704127605770444906854175870243452753002238589530499630034663296166308443155999957196346563161387705205277189957388653461251461388391745795979375660087266037741360406956289962327970672363315696841378765492754546688",
|
||||||
"-0.825575442809343611824362325239811764094510857054278582264067433862269037693599066167126550050055810893236466513641579446123546053932400340779013543022627343780304207889697484852104716170210387967098979368968667582761587933736919053415297219989844530337025837550322738303417999408570541023209479831053490074672524731593393200211612747267787376420912055466715589243670137116181283653627378091767001266729750523670904813955028404725364549436654773973161631448021217524149606880882398338428340541423336476442278764927060929088442662022809429880029452211569992113848964950861453209500601571720208371076364637312918805739974730928391130012733244321591317884640789514132100142038718855057870855384682083191451172141637084656463668180074273357513986650562276924927490092054490207521493248546634803683905992004777812863248355102626794030220223795127136641375381651724046389855784239897808572076152799212203148992979849462537797025824681362178656342679605636982892165755312758468261428421302359039383473990693745647491195856344807310687765672840471336376933282820265780965117564858639226791165667469629053398278240657443123596015059287606479740468263567953594727359402416208210264162078048896806628308236533843407536450642386891796397818074083632855343175466156403711148552219179067451933509186842662133841059218230787130271284099320325244795528905606899665072032213644123281103167139222988313296269780039438046514987945556640625",
|
"-0.82557544253149396284458404188071504476091346830440347376462206521981928020803354950315062147200396866217255527509254080721982393941347365824137698491042935894213870423296625749297033966815252917361266452901192457318047750698424190124169875103436588397415032138037063155981648677895645409699825582226442363080800781881653440538927704569142007751338851079530521979429507520541625303794665680584709171813053216867014700596866196844144286737568957809383224972108999354839705480223052622003994027222120126949093911643497423100187973906980635670000034664323357488815820848035808846624518774608931622703631130673844138378087837990739103263093532314835289302930152150130664948083902949999427848344301686172490282395687167681679607401220592559832932068966455384902377056623736013617949634746332323529256184776892339963173795176200590119077305668901887229709592836744082027738666294887303249770621722032438202753270710379312736193201366287952361100525126056993039858894987153270630277483613793395809214871734783742285495171911648254647287555645360520115341268930844095156502348405343740866836850201634640011708462641462047870611041595707018966032206807675586825362640000739202116391403514629284000986232673698892843586989003952425039512325844566790376383098534975022847888104706525937115931692008959513984157709954859352131323440787667052399474107219968",
|
||||||
}
|
}
|
||||||
for i, inp := range inps {
|
for i, inp := range inps {
|
||||||
d, err := NewFromString(inp)
|
d, err := NewFromString(inp)
|
||||||
|
@ -2418,18 +2548,18 @@ func TestTan(t *testing.T) {
|
||||||
"1.0",
|
"1.0",
|
||||||
"5.0",
|
"5.0",
|
||||||
"10",
|
"10",
|
||||||
"11000020.2407442310156021090304691671842603586882014729198302312846062338790031898128063403419218957424",
|
"11000020.2407442310156021090304691671842603586882014729198302312846062338790031898128063403419218957424",
|
||||||
}
|
}
|
||||||
sols := []string{
|
sols := []string{
|
||||||
"0.226141565050579195128504091376587961550743024795950198353192839504353407742431869564825319685041904449462890625",
|
"0.2261415650505790298980791606748881031998682652",
|
||||||
"-1.5574077246549022",
|
"-1.5574077246549025",
|
||||||
"-0.255341921221036275",
|
"-0.255341921221036275",
|
||||||
"0.0",
|
"0.0",
|
||||||
"0.342524867530038963",
|
"0.342524867530038963",
|
||||||
"1.5574077246549022",
|
"1.5574077246549025",
|
||||||
"-3.3805150062465857",
|
"-3.3805150062465829",
|
||||||
"0.648360827459086657992079596346674836000458368506527382600293171822426231687419573290753760375082492828369140625",
|
"0.6483608274590872485524085572681343280321117494",
|
||||||
"0.683513254892486971935899897806108130234891903543492515192842067427622421368508870073710248504975849182264766875",
|
"0.68351325561491170753499935023939368502774607234006019034769919811202010905597996164029250820702097041244539696",
|
||||||
}
|
}
|
||||||
for i, inp := range inps {
|
for i, inp := range inps {
|
||||||
d, err := NewFromString(inp)
|
d, err := NewFromString(inp)
|
||||||
|
@ -2446,3 +2576,23 @@ func TestTan(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExampleNewFromFloat32() {
|
||||||
|
fmt.Println(NewFromFloat32(123.123123123123).String())
|
||||||
|
fmt.Println(NewFromFloat32(.123123123123123).String())
|
||||||
|
fmt.Println(NewFromFloat32(-1e13).String())
|
||||||
|
// OUTPUT:
|
||||||
|
//123.12312
|
||||||
|
//0.123123124
|
||||||
|
//-10000000000000
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleNewFromFloat() {
|
||||||
|
fmt.Println(NewFromFloat(123.123123123123).String())
|
||||||
|
fmt.Println(NewFromFloat(.123123123123123).String())
|
||||||
|
fmt.Println(NewFromFloat(-1e13).String())
|
||||||
|
// OUTPUT:
|
||||||
|
//123.123123123123
|
||||||
|
//0.123123123123123
|
||||||
|
//-10000000000000
|
||||||
|
}
|
||||||
|
|
118
rounding.go
Normal file
118
rounding.go
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Multiprecision decimal numbers.
|
||||||
|
// For floating-point formatting only; not general purpose.
|
||||||
|
// Only operations are assign and (binary) left/right shift.
|
||||||
|
// Can do binary floating point in multiprecision decimal precisely
|
||||||
|
// because 2 divides 10; cannot do decimal floating point
|
||||||
|
// in multiprecision binary precisely.
|
||||||
|
package decimal
|
||||||
|
|
||||||
|
type floatInfo struct {
|
||||||
|
mantbits uint
|
||||||
|
expbits uint
|
||||||
|
bias int
|
||||||
|
}
|
||||||
|
|
||||||
|
var float32info = floatInfo{23, 8, -127}
|
||||||
|
var float64info = floatInfo{52, 11, -1023}
|
||||||
|
|
||||||
|
// roundShortest rounds d (= mant * 2^exp) to the shortest number of digits
|
||||||
|
// that will let the original floating point value be precisely reconstructed.
|
||||||
|
func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) {
|
||||||
|
// If mantissa is zero, the number is zero; stop now.
|
||||||
|
if mant == 0 {
|
||||||
|
d.nd = 0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute upper and lower such that any decimal number
|
||||||
|
// between upper and lower (possibly inclusive)
|
||||||
|
// will round to the original floating point number.
|
||||||
|
|
||||||
|
// We may see at once that the number is already shortest.
|
||||||
|
//
|
||||||
|
// Suppose d is not denormal, so that 2^exp <= d < 10^dp.
|
||||||
|
// The closest shorter number is at least 10^(dp-nd) away.
|
||||||
|
// The lower/upper bounds computed below are at distance
|
||||||
|
// at most 2^(exp-mantbits).
|
||||||
|
//
|
||||||
|
// So the number is already shortest if 10^(dp-nd) > 2^(exp-mantbits),
|
||||||
|
// or equivalently log2(10)*(dp-nd) > exp-mantbits.
|
||||||
|
// It is true if 332/100*(dp-nd) >= exp-mantbits (log2(10) > 3.32).
|
||||||
|
minexp := flt.bias + 1 // minimum possible exponent
|
||||||
|
if exp > minexp && 332*(d.dp-d.nd) >= 100*(exp-int(flt.mantbits)) {
|
||||||
|
// The number is already shortest.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// d = mant << (exp - mantbits)
|
||||||
|
// Next highest floating point number is mant+1 << exp-mantbits.
|
||||||
|
// Our upper bound is halfway between, mant*2+1 << exp-mantbits-1.
|
||||||
|
upper := new(decimal)
|
||||||
|
upper.Assign(mant*2 + 1)
|
||||||
|
upper.Shift(exp - int(flt.mantbits) - 1)
|
||||||
|
|
||||||
|
// d = mant << (exp - mantbits)
|
||||||
|
// Next lowest floating point number is mant-1 << exp-mantbits,
|
||||||
|
// unless mant-1 drops the significant bit and exp is not the minimum exp,
|
||||||
|
// in which case the next lowest is mant*2-1 << exp-mantbits-1.
|
||||||
|
// Either way, call it mantlo << explo-mantbits.
|
||||||
|
// Our lower bound is halfway between, mantlo*2+1 << explo-mantbits-1.
|
||||||
|
var mantlo uint64
|
||||||
|
var explo int
|
||||||
|
if mant > 1<<flt.mantbits || exp == minexp {
|
||||||
|
mantlo = mant - 1
|
||||||
|
explo = exp
|
||||||
|
} else {
|
||||||
|
mantlo = mant*2 - 1
|
||||||
|
explo = exp - 1
|
||||||
|
}
|
||||||
|
lower := new(decimal)
|
||||||
|
lower.Assign(mantlo*2 + 1)
|
||||||
|
lower.Shift(explo - int(flt.mantbits) - 1)
|
||||||
|
|
||||||
|
// The upper and lower bounds are possible outputs only if
|
||||||
|
// the original mantissa is even, so that IEEE round-to-even
|
||||||
|
// would round to the original mantissa and not the neighbors.
|
||||||
|
inclusive := mant%2 == 0
|
||||||
|
|
||||||
|
// Now we can figure out the minimum number of digits required.
|
||||||
|
// Walk along until d has distinguished itself from upper and lower.
|
||||||
|
for i := 0; i < d.nd; i++ {
|
||||||
|
l := byte('0') // lower digit
|
||||||
|
if i < lower.nd {
|
||||||
|
l = lower.d[i]
|
||||||
|
}
|
||||||
|
m := d.d[i] // middle digit
|
||||||
|
u := byte('0') // upper digit
|
||||||
|
if i < upper.nd {
|
||||||
|
u = upper.d[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Okay to round down (truncate) if lower has a different digit
|
||||||
|
// or if lower is inclusive and is exactly the result of rounding
|
||||||
|
// down (i.e., and we have reached the final digit of lower).
|
||||||
|
okdown := l != m || inclusive && i+1 == lower.nd
|
||||||
|
|
||||||
|
// Okay to round up if upper has a different digit and either upper
|
||||||
|
// is inclusive or upper is bigger than the result of rounding up.
|
||||||
|
okup := m != u && (inclusive || m+1 < u || i+1 < upper.nd)
|
||||||
|
|
||||||
|
// If it's okay to do either, then round to the nearest one.
|
||||||
|
// If it's okay to do only one, do it.
|
||||||
|
switch {
|
||||||
|
case okdown && okup:
|
||||||
|
d.Round(i + 1)
|
||||||
|
return
|
||||||
|
case okdown:
|
||||||
|
d.RoundDown(i + 1)
|
||||||
|
return
|
||||||
|
case okup:
|
||||||
|
d.RoundUp(i + 1)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue