Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dealing with floating point number precision in Go arithmetic?

I'm interested in a way to accurately subtract 2 float's in Go.

I've tried to use the math/big library but I can't get an accurate result.

I've used the big.js library in Javascript which solves this problem. Is there a similar library/method for Go arithmetic?

    package main

    import (
        "fmt"
        "math/big"
    )

    func main() {
        const prec = 200
        a := new(big.Float).SetPrec(prec).SetFloat64(5000.0)
        b := new(big.Float).SetPrec(prec).SetFloat64(4000.30)
        result := new(big.Float).Sub(a, b)
        fmt.Println(result)
    }
    Result: 999.6999999999998181010596454143524169921875

https://play.golang.org/p/vomAr87Xln

like image 474
patrick-fitzgerald Avatar asked Sep 22 '17 23:09

patrick-fitzgerald


People also ask

How do you find the precision of a floating point?

The precision of floating-point numbers is either single or double, based on the number of hexadecimal digits in the fraction. A small integer is a binary integer with a precision of 15 bits. The range of small integers is -32768 to +32767. A large integer is a binary integer with a precision of 31 bits.

How do you change the precision of a float?

Floats have a static, fixed precision. You can't change it.


1 Answers

Package big

import "math/big"

func (*Float) String

func (x *Float) String() string

String formats x like x.Text('g', 10). (String must be called explicitly, Float.Format does not support %s verb.)

Use string input and round the output, for example,

package main

import (
    "fmt"
    "math/big"
)

func main() {
    const prec = 200
    a, _ := new(big.Float).SetPrec(prec).SetString("5000")
    b, _ := new(big.Float).SetPrec(prec).SetString("4000.30")
    result := new(big.Float).Sub(a, b)
    fmt.Println(result)
    fmt.Println(result.String())
}

Output:

999.6999999999999999999999999999999999999999999999999999999995
999.7

For decimal, by definition, binary floating-point numbers are an approximation. For example, the decimal number 0.1 cannot be represented exactly, it is approximately 1.10011001100110011001101 * (2**(-4)).

You are already used to this sort of thing since you know about repeating decimals, an approximation for rational numbers: 1 / 3 = .333... and 3227 / 555 = 5.8144144144....

See What Every Computer Scientist Should Know About Floating-Point Arithmetic.

like image 183
peterSO Avatar answered Nov 15 '22 09:11

peterSO