"math/rand"
"reflect"
. "strconv"
+ "strings"
"testing"
"time"
)
// A very large number (initially wrongly parsed by the fast algorithm).
{"4.630813248087435e+307", "4.630813248087435e+307", nil},
+
+ // A different kind of very large number.
+ {"22.222222222222222", "22.22222222222222", nil},
+ {"2." + strings.Repeat("2", 4000) + "e+1", "22.22222222222222", nil},
+
+ // Exactly halfway between 1 and math.Nextafter(1, 2).
+ // Round to even (down).
+ {"1.00000000000000011102230246251565404236316680908203125", "1", nil},
+ // Slightly lower; still round down.
+ {"1.00000000000000011102230246251565404236316680908203124", "1", nil},
+ // Slightly higher; round up.
+ {"1.00000000000000011102230246251565404236316680908203126", "1.0000000000000002", nil},
+ // Slightly higher, but you have to read all the way to the end.
+ {"1.00000000000000011102230246251565404236316680908203125" + strings.Repeat("0", 10000) + "1", "1.0000000000000002", nil},
}
type atofSimpleTest struct {
package strconv
type decimal struct {
- // TODO(rsc): Can make d[] a bit smaller and add
- // truncated bool;
- d [800]byte // digits
- nd int // number of digits used
- dp int // decimal point
- neg bool
+ d [800]byte // digits
+ nd int // number of digits used
+ dp int // decimal point
+ neg bool
+ trunc bool // discarded nonzero digits beyond d[:nd]
}
func (a *decimal) String() string {
for n > 0 {
dig := n >> k
n -= dig << k
- a.d[w] = byte(dig + '0')
- w++
+ if w < len(a.d) {
+ a.d[w] = byte(dig + '0')
+ w++
+ } else if dig > 0 {
+ a.trunc = true
+ }
n = n * 10
}
quo := n / 10
rem := n - 10*quo
w--
- a.d[w] = byte(rem + '0')
+ if w < len(a.d) {
+ a.d[w] = byte(rem + '0')
+ } else if rem != 0 {
+ a.trunc = true
+ }
n = quo
}
quo := n / 10
rem := n - 10*quo
w--
- a.d[w] = byte(rem + '0')
+ 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)
}
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
}
// Round a to nd digits (or fewer).
-// Returns receiver for convenience.
// If nd is zero, it means we're rounding
// just to the left of the digits, as in
// 0.09 -> 0.1.
}
// Round a down to nd digits (or fewer).
-// Returns receiver for convenience.
func (a *decimal) RoundDown(nd int) {
if nd < 0 || nd >= a.nd {
return
}
// Round a up to nd digits (or fewer).
-// Returns receiver for convenience.
func (a *decimal) RoundUp(nd int) {
if nd < 0 || nd >= a.nd {
return