Skip to content

Instantly share code, notes, and snippets.

@x1unix
Created August 10, 2020 15:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save x1unix/81fb07f59868ec093c5892a70e4f8d81 to your computer and use it in GitHub Desktop.
Save x1unix/81fb07f59868ec093c5892a70e4f8d81 to your computer and use it in GitHub Desktop.
Go: precise float parse
package main
import (
"fmt"
)
// ParseFloatPrecisely parses floating point from string as strconv.ParseFloat
// but avoids float point precision issue (ex: "0.21" parsed as 0.209999)
func ParseFloatPrecisely(str string, bitSize int) (num float64, err error) {
if str == "" || str == "0" {
return 0, nil
}
chunks := strings.SplitN(str, ".", 2)
mantissaPart := chunks[0]
isNegative := mantissaPart[0] == '-'
mantissa, err := strconv.ParseInt(mantissaPart, 10, bitSize)
if err != nil {
return 0, fmt.Errorf("ParseFloat: failed to parse mantissa part of number (%w)", err)
}
if len(chunks) < 2 {
return float64(mantissa), nil
}
expoLen := len(chunks[1])
expoPart, err := strconv.ParseUint(chunks[1], 10, bitSize)
if err != nil {
return 0, fmt.Errorf("ParseFloat: failed to parse exponent part of number (%w)", err)
}
if expoPart == 0 {
return float64(mantissa), nil
}
// concat exponent and mantissa to make f64 number
exponent := float64(expoPart) / math.Pow10(expoLen)
if isNegative {
exponent *= -1
}
num = float64(mantissa) + exponent
return num, nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment