aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--decimal-go.go414
-rw-r--r--decimal.go81
-rw-r--r--decimal_test.go234
-rw-r--r--rounding.go118
4 files changed, 798 insertions, 49 deletions
diff --git a/decimal-go.go b/decimal-go.go
new file mode 100644
index 0000000..e08a15c
--- /dev/null
+++ b/decimal-go.go
@@ -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
+}
diff --git a/decimal.go b/decimal.go
index 62c7175..134ece2 100644
--- a/decimal.go
+++ b/decimal.go
@@ -171,17 +171,84 @@ func RequireFromString(value string) Decimal {
// NewFromFloat converts a float64 to Decimal.
//
-// Example:
-//
-// NewFromFloat(123.45678901234567).String() // output: "123.4567890123456"
-// NewFromFloat(.00000000000000001).String() // output: "0.00000000000000001"
+// 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.
//
-// 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.
+// For slightly faster conversion, use NewFromFloatWithExponent where you can specify the precision in absolute terms.
//
// NOTE: this will panic on NaN, +/-inf
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
diff --git a/decimal_test.go b/decimal_test.go
index 7a6f37e..64f0552 100644
--- a/decimal_test.go
+++ b/decimal_test.go
@@ -4,13 +4,16 @@ import (
"database/sql/driver"
"encoding/json"
"encoding/xml"
+ "fmt"
"math"
"math/big"
+ "math/rand"
"reflect"
"sort"
"strconv"
"strings"
"testing"
+ "testing/quick"
"time"
)
@@ -42,9 +45,19 @@ var testTable = []*testEnt{
{.1000000000000003, "0.1000000000000003", "", "0.1000000000000003000000000000001234123412"},
{.1000000000000005, "0.1000000000000005", "", "0.1000000000000005000000000000000006441234"},
{.1000000000000008, "0.1000000000000008", "", "0.100000000000000800000000000000000009999999999999999999999999999"},
- {1e25, "10000000000000000000000000", "", "10000000000000000000000000.00000000000000000098798978"},
- {math.MaxInt64, strconv.FormatInt(math.MaxInt64, 10), "", strconv.FormatInt(math.MaxInt64, 10)},
- {1.29067116156722e-309, "0", "", "0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001290671161567218558822290567835270536800098852722416870074139002112543896676308448335063375297788379444685193974290737962187240854947838776604607190387984577130572928111657710645015086812756013489109884753559084166516937690932698276436869274093950997935137476803610007959500457935217950764794724766740819156974617155861568214427828145972181876775307023388139991104942469299524961281641158436752347582767153796914843896176260096039358494077706152272661453132497761307744086665088096215425146090058519888494342944692629602847826300550628670375451325582843627504604013541465361435761965354140678551369499812124085312128659002910905639984075064968459581691226705666561364681985266583563078466180095375402399087817404368974165082030458595596655868575908243656158447265625000000000000000000000000000000000000004440000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},
+ {1e25, "10000000000000000000000000", "", ""},
+ {1.5e14, "150000000000000", "", ""},
+ {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{
@@ -89,11 +102,11 @@ func init() {
func TestNewFromFloat(t *testing.T) {
for _, x := range testTable {
- s := x.exact
+ s := x.short
d := NewFromFloat(x.float)
if d.String() != s {
- t.Errorf("expected %s, got %s (%s, %d)",
- s, d.String(),
+ t.Errorf("expected %s, got %s (float: %v) (%s, %d)",
+ s, d.String(), x.float,
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) {
for _, x := range testTable {
s := x.short
@@ -151,6 +279,9 @@ func TestNewFromString(t *testing.T) {
func TestFloat64(t *testing.T) {
for _, x := range testTable {
+ if x.inexact == "" || x.inexact == "-" {
+ continue
+ }
s := x.exact
d, err := NewFromString(s)
if err != nil {
@@ -2298,18 +2429,18 @@ func TestAtan(t *testing.T) {
"1.0",
"5.0",
"10",
- "11000020.2407442310156021090304691671842603586882014729198302312846062338790031898128063403419218957424",
+ "11000020.2407442310156021090304691671842603586882014729198302312846062338790031898128063403419218957424",
}
sols := []string{
- "-1.2407643882205801102743706275310603586882014729198302312846062338790031898128063403419218957424163818359375",
- "-0.78539816339744833061616997868383017934410073645991511564230311693950159490640317017096094787120819091796875",
+ "-1.24076438822058001027437062753106",
+ "-0.78539816339744833061616997868383",
"-0.24497866312686415",
"0.0",
"0.318747560420644443",
- "0.78539816339744833061616997868383017934410073645991511564230311693950159490640317017096094787120819091796875",
- "1.3734007669450159012323399573676603586882014729198302312846062338790031898128063403419218957424163818359375",
- "1.4711276743037346312323399573676603586882014729198302312846062338790031898128063403419218957424163818359375",
- "1.5707962358859730612325945023537403586882014729198302312846062338790031898128063403419218957424163818359375",
+ "0.78539816339744833061616997868383",
+ "1.37340076694501580123233995736766",
+ "1.47112767430373453123233995736766",
+ "1.57079623588597296123259450235374",
}
for i, inp := range inps {
d, err := NewFromString(inp)
@@ -2338,18 +2469,17 @@ func TestSin(t *testing.T) {
"1.0",
"5.0",
"10",
- "11000020.2407442310156021090304691671842603586882014729198302312846062338790031898128063403419218957424",
- }
- sols := []string{
- "-0.220571862520030093613839729898389234591448264443828979962999436149729548845614563657783710150808249493659603883785557750857064742068654401611592366453156979425089038732558977915147138610177101332138819745624841999009731533470874398791630404814623756725761484209848526893621903868344844362592350061614721709283168025028307789990557501123216276655612701350632840149744527732872833304632776220881820168763715880072271900752263175824768749676997835634284780882959485313122780499486873741058283218325040301421620652217699025347852371634749059985101913743575566482455108757945784327770283152556778940395109157571785095552777237471737930299497127855782791647416409676751196562400230573256919649166116220548146722732673811940013822174052471575484241086300786209457059067702404625074214637302180559257156598478224357461349695824437855046828206155188482292930722180491096361781653423287753045189099820938975700063357767823639345982521057442719437079960883170296730778877529726323641962581167118741985973085143794261349309399843621404104514700512532703761239968546841161640494797236796414402075947283426422877298624337798757146020442229118476349906575010431352541089067121029579490866064323880357132858662072455977109093817967157613567800944577216024589669093782841129397681562208313003621389103425798339230823330581188201904296875",
- "-0.84147098480789650683573384227719871264659725213827912307678945963233888758666252541652307542471941569920950873234694687123276222626964952320957348347806244448304658355378064371162688704108432893734339281119107889886243608606771440333499496399246182550579552307436056577989755048676139388257574972355638331020916986327112812449023235994235220681962126402627149122741398037411569225585167209440887381294958909446263040889436515610243685011381400045762457675558838333095494482138227725013381292722259213324814381642325470123171162316406069142833674558352099403808484142312206036567122374357983536120130367436871049536150555321227634134943262101222587962853023526365048081446005272233936756658798560188088496199440605960018665932771208203273875932636591008594752836095901878899636892331191188133444513639520743904232369072391326448163751628578886099960312207261234582748222511007033947148867295201489673608530271710726980420265749989442268185776660104680951516862727780322815011940555693819786827407000470928166813302681223319136916385379500478197064927760223020342764479386095349145229773585152310192696649682836151684354735282894320955021997802761069713870309184654536840910246184967655772931790056052366745119986847633246318705770507591911530119455091063686301656648189606417807689546576464738456252196397075290117772324937902655849801056962584258183367906235526162380299193832940968379238027598232552151102936477400362491607666015625",
- "-0.247403959254522929719728461264852108650160857317149198152655832001777826134603088803487480618059635162353515625",
- "0.0",
- "0.324043028394868345912501559420824735488967340443112210114701957327566252120565337691004970110952854156494140625",
- "0.84147098480789650683573384227719871264659725213827912307678945963233888758666252541652307542471941569920950873234694687123276222626964952320957348347806244448304658355378064371162688704108432893734339281119107889886243608606771440333499496399246182550579552307436056577989755048676139388257574972355638331020916986327112812449023235994235220681962126402627149122741398037411569225585167209440887381294958909446263040889436515610243685011381400045762457675558838333095494482138227725013381292722259213324814381642325470123171162316406069142833674558352099403808484142312206036567122374357983536120130367436871049536150555321227634134943262101222587962853023526365048081446005272233936756658798560188088496199440605960018665932771208203273875932636591008594752836095901878899636892331191188133444513639520743904232369072391326448163751628578886099960312207261234582748222511007033947148867295201489673608530271710726980420265749989442268185776660104680951516862727780322815011940555693819786827407000470928166813302681223319136916385379500478197064927760223020342764479386095349145229773585152310192696649682836151684354735282894320955021997802761069713870309184654536840910246184967655772931790056052366745119986847633246318705770507591911530119455091063686301656648189606417807689546576464738456252196397075290117772324937902655849801056962584258183367906235526162380299193832940968379238027598232552151102936477400362491607666015625",
- "-0.95892427466313846886683534084169138601699178595056142681129038893400410281163045903621198874295374290149806823897075576057724999482959874362888984630786877750800707948164478439888413437709227541296453939066231042449153560817956529124771991719434464325257307490209688817348630841990228088502580219431623697760216390920129365244393334429239217501291865772417470981461975427863913628459487634361457463896191397206119089801538318057594728767278995563353925328463456560840888895608182514323808823801838724482524462741712473496938668730262585034295941891365544300178534659369917661430555201335114597830077556398746790054730682231578093617522006106659977088453875512527401574137870617360741477467052899927465250688663724908651769559466919777914497651416655110015287957761809374118954830175592272643086681859204507636705728518901196924686915642366269243409467335313632803457424138328976320449572075303129501941586734619627126950347146441488301272523732890971103193432131967093584975094064352688636321088866275878367912478080039614015674090467373532503838989934725811696669260106530065305130564789502177378344025691707116401561519233199329283661803416619394138904068356512359009119169667571681552281997620458915816124425995894145459910451225779660911316891499301549117918834162954131295015995478902576153796243561887919093281708146016725119431774666779045011119428333353937254827947830587875729623490751729608660980375134386122226715087890625",
- "-0.544021110889369814404798546234261521735237410341301440744913863554325413910729487222404754912397132389280869582562649416317020824255899391102716253549602359933406667420857908751554064982667505778980864397665237869392769251295144996601379178780771501957858736340861984904014191524939793604688756271913886434778180316203812548425041682948461830667971245994025528380063656691687013885731759172341309655658172703937945366976128597657101230629806658897303549468649147494313422814604383947907342285887634159176609268080528703630505118954169027929142559898709956536517735787676487117591429732597764129997800544321069045676840705169697409709450991200259966568075515292000715246707423119024660809599616729869855242609248565503156233847151639381625642548896051440565640966333400046266460293523862957282305141303657282623793830073310394349418290939283661501995774676808852008306303431767521000117474347792119119745767325061425517820206720145795639782171641765977980488850129569363740173287329545019826050789666603219553652178298235868990551128361160456166647394642535572127727629420370720856130359966967599668830582910424823037763854828905673063487188976311335956440851988180468345725600705105113853947651574770698730911647817190648000646872041955859376392859382055300138695355787127336060458870914402496055117808282375335693359375",
- "-0.564291758073920672156060501108780948637502927903402695682970758082173347334144085493099932047342878232107294208163423635351694839181128599190761981992082190183414367145761958978263205360050276797203465120166463337285861568628620441149869080262018002460551105733370384496691552603807079787064355499979892738941692390909198368605275928720995456124329350110140031040327865030504338978174244479702663590952255309812151905391076362043165507118546398673253957125454990703254702293833362635280840010399956637688760201442320428708562854314419339362472820724298986435162931641340060501848890585327411159080467227885852591584159465243368331681937734746160681439404005233844642476786199607795910618003577395193096223575912506207477927572401934790710176468073033112942732454695154492720511230782735184156027155137618173659003878927697237751139877779082916148874086491265428313018347132700490228131397266369640661232003084568637049642401980172435548737268283623715380443755530399410106957744899992161330205161097513785489406292271887390739430612193060474304401657511461250218562733033893187306639264886516827894130028111468708805823753758224864450015655567869605537758979198887215555526950741196023433812962018677695204317878927956155283357420412564940844662156159296973147878187706628631717213628871121500196750275790691375732421875",
+ "11000020.2407442310156021090304691671842603586882014729198302312846062338790031898128063403419218957424",
+ }
+ sols := []string{"-0.22057186252002995641471297726318877448242875710373383657841216606788849153474483300147427943530288911869356126149550184271061369789963810497434594683859566879253561990821788142048867910104964466745284318577343435957806286762494529983369776697504436326725441516925396488258485248699247367113416543705253919473126183478178486954138205996912770183192357029798618739277146694040778731661407420114923656224752540889120768",
+ "-0.841470984807896544828551915928318375739843472469519282898610111931110319333748010828751784005573402229699531838022117989945539661588502120624574802425114599802714611508860519655182175315926637327774878594985045816542706701485174683683726979309922117859910272413672784175028365607893544855897795184024100973080880074046886009375162838756876336134083638363801171409953672944184918309063800980214873465660723218405962257950683415203634506166523593278",
+ "-0.2474039592545229296662577977006816864013671875",
+ "0",
+ "0.3240430283948683457891331120415701894104386268737728",
+ "0.841470984807896544828551915928318375739843472469519282898610111931110319333748010828751784005573402229699531838022117989945539661588502120624574802425114599802714611508860519655182175315926637327774878594985045816542706701485174683683726979309922117859910272413672784175028365607893544855897795184024100973080880074046886009375162838756876336134083638363801171409953672944184918309063800980214873465660723218405962257950683415203634506166523593278",
+ "-0.958924274663138409032065951037351417114444405831206421994322505831797734568720303321152847999323782235893449831846516332891972309733806145798957570823292783131379570446989311599459252931842975162373777189193072018951049969744350662993214861042908755303566670204873618202680865638534865944483058650517380292320436016362659617294570185140789829574277032406195741535138712427510938542219940873171248862329526140744770994303733112530324791184417282382",
+ "-0.54402111088937016772477554483765124109312606762621462357463994520238396180161585438877562935656067241573063207614488370477645194661241525080677431257416988398683714890165970942834453391033857378247849486306346743023618509617104937236345831462093934032592562972419977883837745736210439651143668255744843041350221801750331646628192115694352540293150183983357476391787825596543270240461102629075832777618592034309799936",
+ "-0.564291758480422881634770440632390475980828840253516895637281099241819037882007239070203007530085741820184955492382572029153491807930868879341091067301689987699567034024159005627332722089169680203292567574310010066799858914647295684974242359142300929248173166551428537696685165964880390889406578530338963341989826231514301546476672476399906348023294571001061677668735117509440368611093448917120819545826797975989350435900286332895885871219875665471968941335407351099209738417818747252638912592184093301853338763294381446907254104878969784040526201729163408095795934201105630182851806342356035203279670146684553491616847294749721014579109870396804713831114709372638323643327823671187472335866664108658093206409882794958673673978956925250261545083579947618620746006004554405785185537391110314728988164693223775249484198058394348289545771967707968288542718255197272633789792059019367104377340604030147471453833808674013259696102003732963091159662478879760121731138091114134586544668859915547568540172541576138084166990547345181184322550297604278946942918844039406876827936831612756344331500301118652183156052728447906384772901595431751550607818380262138322673253023464533931883787069611052589166000316238423939491520880451263927981787175602294299295744",
}
for i, inp := range inps {
d, err := NewFromString(inp)
@@ -2378,18 +2508,18 @@ func TestCos(t *testing.T) {
"1.0",
"5.0",
"10",
- "11000020.2407442310156021090304691671842603586882014729198302312846062338790031898128063403419218957424",
+ "11000020.2407442310156021090304691671842603586882014729198302312846062338790031898128063403419218957424",
}
sols := []string{
- "-0.975370726167463436728505866323714237868918798735337852490354630275400590397256757982930518671177656988788392411709345759154371178337418085499048191038650091945778580197329516971729513331012900776507504230803826799226710606177535289143559059224362661001603838745169803182674368143452935332062804519861768577138064573259069358975042122485627388192604101700302462362798592115038066626006203292151971117547825788365029212778673068841445412348366566041687247190622871297208478844658065023427261675103854131453079888921085982507674462174796122088474426882259116347806427809304457623578281770915649130727943036401841073052876646614496797452163682420483896962238944883515469778180754205404941121141599952645904787654598990827384683885441411829970587806867632776521257761008506280475694989732289455150722563701599552835784792787892378475275568451704113581492707873602587027241507884412830033365653914549639245334821262039117311046735253960816076120011217151854994903031629514573221302055487026138480621515317251868170670711382669181677841187033304861609062981031260474272177938456322715827189878292157663041430578246790062347759217920400856872733420989333068628730367636465064551304273677450773043171019346261214827671284261815921602597267030573778706635242318228554033918329328451836597811660816887574069149657366695399451977163530476815743551656054860762997757628606444388219917589048259254358441694421344436705112457275390625",
- "0.5403023058681397185594704958555785318789737039530258806063132922287686731767103380722879951346341700301934154242672285869862285136280035256635149087722026456653060623287636554810379311566025776640284286043366692017812351065106848975433243878434601646053373656175870219143335780037780263780528022552589948882631781788387243759097393407418459341665025578959743680402679565710214589639277870162089735459876789876164945626397889278949094061300698882180972876375063478762441763141045691438279791675986386217937407677843979434037325100615614204173839676230023544297002103390623811623287987178412049715000660987495684907814359780765658960715423795658408220614069561530422742718922893554271137549412369147629593458239490366605797325139239944180051692566520667214675204069476110320173267646327440417945329562672924843423546460029298423629611979148079742086487910832189641973781754022003095306885302971446512196936121388134045074972570593581133444925052909080976768554628154520121141808489601642421723177702083881285314379847744230155051966361158007017591582046619808944751148550841102122653076944135728372456492657514171872121435155305860386442665726120257630353953444221670261220705805623292334551636518107895571396829211893470388375917284217734121333575035514871632238034279250742569584498765995392820238318876135963364504277706146240234375",
- "0.968912421710644784098953478920868172610959295777507211448260716808741793725813506998889579335809685289859771728515625",
- "1.0",
- "0.946042343528386971548655274719127421974169853736868957009626534392384054569270779300182994120405055582523345947265625",
- "0.5403023058681397185594704958555785318789737039530258806063132922287686731767103380722879951346341700301934154242672285869862285136280035256635149087722026456653060623287636554810379311566025776640284286043366692017812351065106848975433243878434601646053373656175870219143335780037780263780528022552589948882631781788387243759097393407418459341665025578959743680402679565710214589639277870162089735459876789876164945626397889278949094061300698882180972876375063478762441763141045691438279791675986386217937407677843979434037325100615614204173839676230023544297002103390623811623287987178412049715000660987495684907814359780765658960715423795658408220614069561530422742718922893554271137549412369147629593458239490366605797325139239944180051692566520667214675204069476110320173267646327440417945329562672924843423546460029298423629611979148079742086487910832189641973781754022003095306885302971446512196936121388134045074972570593581133444925052909080976768554628154520121141808489601642421723177702083881285314379847744230155051966361158007017591582046619808944751148550841102122653076944135728372456492657514171872121435155305860386442665726120257630353953444221670261220705805623292334551636518107895571396829211893470388375917284217734121333575035514871632238034279250742569584498765995392820238318876135963364504277706146240234375",
- "0.2836621854632262640413454705014792126730041372592792257206146645426601396441260356011571632089582618925838153657699769828738164020634023542401271546832973668591965970780399287846132178786932147719489387057249755694634919271032742386467263343003762216059912285589934893404186137482489686474984451054771103493648603655340770275593072267521598532667125806036270513157359920795997662877180316554125323347714021810156977000099765637673158040510070215919734518464013962899531358902754977185164550708058199871247160015886870149163066556093196783440812874006182781633602366172183573725257608628866745555998550377960547686470245458626674802626292796549871502254193653242073557087898962773658255810053531370802115864997325060870572958692356612208396119690852149106422002310275167937817158288794799498840438933404405058238604063789542363766559068475105058515056790385539505205746157593694133334912162302627008416603294000615739181111749007688625782080015509782711717307370897514073199106746929535880890780214210719294387601483817437596151502942142722181977054762243644235893248214844557965863434535805464134779033144520828071538407409414463996182938827134980848798774952211899634360773590821173224015934994691863733763099257382589344052735164638723090648652823314675360473802118354232333173901927332659182734442282480813446454703807830810546875",
- "-0.839071529076452452453116298055375283024545196907005751226679269494945423257632785713674884440909521085910953206821682885350514489569383484553680293874464258013074629595233233440423524040185080138431677219644537006650333440982266180848432613265727672098505530500860099490052714852637696219860623419861733967504942346257426883650461547676693756422205686582533132927538864456011428540560137047577109540901355332714454892042154044099772961016405398585134639556422987015399944634792029504830682794892974110049771680445087591216461375304720930330852114906188605879368500242393092090599991056282929140339515922705640197683216586300345608814191348583643897583052496585038234458432300602598656172228800591628810870703061601079842675931288590090649649722933122710180797353905585641576282107791663819561479911160784057959370842865399560455463184561649904326467913053219927760200406450092385176263660350059186320075841952511620387666555291853410264149054381143798602019026379808898830628940629734269442061546806433026794983473131041596411391519359668360706593453379582689919628495055879290310156211842712529358591580000339115277557733264569390191184923563095676385834461753760385376605508361399123052214852866448517012467160704995276728328831739643710159503245565807479821789258404871375420699263398077037976545179716664243275062643380243567701961405078734621807138136709079831010972563517559541512724763379083015024662017822265625",
- "-0.825575442809343611824362325239811764094510857054278582264067433862269037693599066167126550050055810893236466513641579446123546053932400340779013543022627343780304207889697484852104716170210387967098979368968667582761587933736919053415297219989844530337025837550322738303417999408570541023209479831053490074672524731593393200211612747267787376420912055466715589243670137116181283653627378091767001266729750523670904813955028404725364549436654773973161631448021217524149606880882398338428340541423336476442278764927060929088442662022809429880029452211569992113848964950861453209500601571720208371076364637312918805739974730928391130012733244321591317884640789514132100142038718855057870855384682083191451172141637084656463668180074273357513986650562276924927490092054490207521493248546634803683905992004777812863248355102626794030220223795127136641375381651724046389855784239897808572076152799212203148992979849462537797025824681362178656342679605636982892165755312758468261428421302359039383473990693745647491195856344807310687765672840471336376933282820265780965117564858639226791165667469629053398278240657443123596015059287606479740468263567953594727359402416208210264162078048896806628308236533843407536450642386891796397818074083632855343175466156403711148552219179067451933509186842662133841059218230787130271284099320325244795528905606899665072032213644123281103167139222988313296269780039438046514987945556640625",
+ "-0.975370726167463467746508538219884948528729295145689640359666742268127382748782064668565276308334226452812521220478854320025773591423493734486361306323829818426063430805234608660356853863442937297855742231573288105774823103008774355455799906250461848079705023428527473474556899228935370709945979509634251305018978306493011197513482210179171510947538040406781879762352211326273272515279567525396877609653501706919545667682725671944948392322552266752",
+ "0.54030230586813965874561515067176071767603141150991567490927772778673118786033739102174242337864109186439207498973007363884202112942385976796862442063752663646870430360736682397798633852405003167527051283327366631405990604840629657123985368031838052877290142895506386796217551784101265975360960112885444847880134909594560331781699767647860744559228420471946006511861233129745921297270844542687374552066388998112901504",
+ "0.968912421710644784099084544806854121387004852294921875",
+ "1",
+ "0.9460423435283869715490383692051286742343482760977712222",
+ "0.54030230586813965874561515067176071767603141150991567490927772778673118786033739102174242337864109186439207498973007363884202112942385976796862442063752663646870430360736682397798633852405003167527051283327366631405990604840629657123985368031838052877290142895506386796217551784101265975360960112885444847880134909594560331781699767647860744559228420471946006511861233129745921297270844542687374552066388998112901504",
+ "0.28366218546322646623291670213892426815646045792775066552057877370468842342090306560693620285882975471913545189522117672866861003904575909174769890684057564495184019705963607555427518763375472432216131070235796577209064861003009894615394882021220247535890708789312783718414424224334988974848162884228012265684775651099758365989567444515619764427493598258393280941942356912304265535918025036942025858493361644535438208",
+ "-0.839071529076452222947082170022504835457755803801719612447629165523199043803440231769716865070163209041973184176293170330332317060558438085478980463542480791358920580076809381102480339018809694514100495572097422057215638383077242523713704127605770444906854175870243452753002238589530499630034663296166308443155999957196346563161387705205277189957388653461251461388391745795979375660087266037741360406956289962327970672363315696841378765492754546688",
+ "-0.82557544253149396284458404188071504476091346830440347376462206521981928020803354950315062147200396866217255527509254080721982393941347365824137698491042935894213870423296625749297033966815252917361266452901192457318047750698424190124169875103436588397415032138037063155981648677895645409699825582226442363080800781881653440538927704569142007751338851079530521979429507520541625303794665680584709171813053216867014700596866196844144286737568957809383224972108999354839705480223052622003994027222120126949093911643497423100187973906980635670000034664323357488815820848035808846624518774608931622703631130673844138378087837990739103263093532314835289302930152150130664948083902949999427848344301686172490282395687167681679607401220592559832932068966455384902377056623736013617949634746332323529256184776892339963173795176200590119077305668901887229709592836744082027738666294887303249770621722032438202753270710379312736193201366287952361100525126056993039858894987153270630277483613793395809214871734783742285495171911648254647287555645360520115341268930844095156502348405343740866836850201634640011708462641462047870611041595707018966032206807675586825362640000739202116391403514629284000986232673698892843586989003952425039512325844566790376383098534975022847888104706525937115931692008959513984157709954859352131323440787667052399474107219968",
}
for i, inp := range inps {
d, err := NewFromString(inp)
@@ -2418,18 +2548,18 @@ func TestTan(t *testing.T) {
"1.0",
"5.0",
"10",
- "11000020.2407442310156021090304691671842603586882014729198302312846062338790031898128063403419218957424",
+ "11000020.2407442310156021090304691671842603586882014729198302312846062338790031898128063403419218957424",
}
sols := []string{
- "0.226141565050579195128504091376587961550743024795950198353192839504353407742431869564825319685041904449462890625",
- "-1.5574077246549022",
+ "0.2261415650505790298980791606748881031998682652",
+ "-1.5574077246549025",
"-0.255341921221036275",
"0.0",
"0.342524867530038963",
- "1.5574077246549022",
- "-3.3805150062465857",
- "0.648360827459086657992079596346674836000458368506527382600293171822426231687419573290753760375082492828369140625",
- "0.683513254892486971935899897806108130234891903543492515192842067427622421368508870073710248504975849182264766875",
+ "1.5574077246549025",
+ "-3.3805150062465829",
+ "0.6483608274590872485524085572681343280321117494",
+ "0.68351325561491170753499935023939368502774607234006019034769919811202010905597996164029250820702097041244539696",
}
for i, inp := range inps {
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
+}
diff --git a/rounding.go b/rounding.go
new file mode 100644
index 0000000..fdd74ea
--- /dev/null
+++ b/rounding.go
@@ -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
+ }
+ }
+}