Created
August 10, 2020 15:23
-
-
Save x1unix/81fb07f59868ec093c5892a70e4f8d81 to your computer and use it in GitHub Desktop.
Go: precise float parse
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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