@@ -480,11 +480,11 @@ func (z *Big) CopySign(x, y *Big) *Big {
480480 return z
481481}
482482
483- // Float64 returns x as a float64 and a bool indicating whether x can be exactly
484- // represented as a float64. Special values are considered exact; however, special
485- // values that occur because the magnitude of x is too large to be represented
486- // as a float64 are not.
487- func (x * Big ) Float64 () (f float64 , exact bool ) {
483+ // Float64 returns x as a float64 and a bool indicating whether x can fit into
484+ // a float64 without truncation, overflow, or underflow. Special values are
485+ // considered exact; however, special values that occur because the magnitude of
486+ // x is too large to be represented as a float64 are not.
487+ func (x * Big ) Float64 () (f float64 , ok bool ) {
488488 if debug {
489489 x .validate ()
490490 }
@@ -505,23 +505,22 @@ func (x *Big) Float64() (f float64, exact bool) {
505505 switch {
506506 case ! x .isCompact ():
507507 f , _ = strconv .ParseFloat (x .String (), 64 )
508- exact = false
509- //f, exact = math.Inf(0), false
508+ ok = ! math .IsInf (f , 0 ) && ! math .IsNaN (f )
510509 case x .compact == 0 :
511- exact = true
510+ ok = true
512511 case x .exp == 0 :
513- f , exact = float64 (x .compact ), true
512+ f , ok = float64 (x .compact ), true
514513 case x .exp > 0 :
515514 f = float64 (x .compact ) * math .Pow10 (x .exp )
516- exact = x .compact < maxMantissa && x .exp < maxPow10
515+ ok = x .compact < maxMantissa && x .exp < maxPow10
517516 case x .exp < 0 :
518517 f = float64 (x .compact ) / math .Pow10 (- x .exp )
519- exact = x .compact < maxMantissa && x .exp > - maxPow10
518+ ok = x .compact < maxMantissa && x .exp > - maxPow10
520519 }
521520 if x .form & signbit != 0 {
522521 f = math .Copysign (f , - 1 )
523522 }
524- return f , exact
523+ return f , ok
525524}
526525
527526// Float sets z to x and returns z. z is allowed to be nil. The result is
@@ -1191,7 +1190,7 @@ func (z *Big) SetFloat64(x float64) *Big {
11911190 }
11921191
11931192 shift := 52 - exp
1194- for mantissa & 1 == 0 {
1193+ for mantissa & 1 == 0 && shift > 0 {
11951194 mantissa >>= 1
11961195 shift --
11971196 }
@@ -1204,19 +1203,18 @@ func (z *Big) SetFloat64(x float64) *Big {
12041203 z .unscaled .Exp (c .FiveInt , & z .unscaled , nil )
12051204 arith .MulUint64 (& z .unscaled , & z .unscaled , mantissa )
12061205 z .exp = - shift
1207- return z .norm ()
1208- }
1209-
1210- if s := uint (- shift ); s < 64 {
1211- z .compact = mantissa << s
1212- z .precision = arith .Length (z .compact )
12131206 } else {
1207+ // TODO(eric): figure out why this doesn't work for _some_ numbers. See
1208+ // https://github.com/ericlagergren/decimal/issues/89
1209+ //
1210+ // z.compact = mantissa << uint(-shift)
1211+ // z.precision = arith.Length(z.compact)
1212+
12141213 z .compact = c .Inflated
12151214 z .unscaled .SetUint64 (mantissa )
1216- z .unscaled .Lsh (& z .unscaled , s )
1217- z .norm ()
1215+ z .unscaled .Lsh (& z .unscaled , uint (- shift ))
12181216 }
1219- return z
1217+ return z . norm ()
12201218}
12211219
12221220// SetInf sets z to -Inf if signbit is set or +Inf is signbit is not set, and
0 commit comments