9

What is the easiest way to get the machine epsilon in Go? What about other aspects of floating point numbers such as precision, min exponent, max exponent, wobble, etc?

I realize that there is the math/const package with the max and min for the different float types (http://golang.org/src/pkg/math/const.go), but no other information.

One reason I would like to know is to verify that I've reached the maximum precision for a given calculation that the machine can do so that I don't quit to early or try longer then needed.

The other is just for curiosity.

Thanks

EDIT:

For the fun I looked up in some notes from school on how to calculate the epsilon manually for fun and here is a rough translation from c++ http://play.golang.org/p/XOXwIdNfsa enjoy

EDIT: comment from below (thanks for a more idiomatic way of finding epsilon):

Use epsilon := math.Nextafter(1, 2) - 1 PlaygroundNick Craig-Wood Mar 5 at 8:07

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
sbditto85
  • 1,485
  • 14
  • 21

2 Answers2

15

It's not defined, I found the issue resolved as "working as intended" on the issue tracker:

https://code.google.com/p/go/issues/detail?id=966

The suggestion seems to be to use math.Nextafter to derive the value if you need it.

Specifically, the formula is math.Nextafter(1.0,2.0)-1.0 (the second argument can be any number greater than 1.0).

Linear
  • 21,074
  • 4
  • 59
  • 70
2

Equation to use

The above works for any binary floating point type (e.g. the Go types you are referring to.)

package main

import "fmt"

func main() {
    f32 := float32(7.)/3 - float32(4.)/3 - float32(1.)
    fmt.Println(f32)

    f64 := float64(7.)/3 - float64(4.)/3 - float64(1.)
    fmt.Println(f64)
}

gives:

-1.1920929e-07
2.220446049250313e-16

taking the absolute (unsigned) value of f32 yields the correct machine ε.

Edit: As mentioned below in a comment from SGJ, this would not work on decimal floating point types, but as far as I'm aware they have not been implemented yet in Golang.

Moustache
  • 394
  • 2
  • 14
  • 2
    Do you know where this formula is derived from? or why it works? – sbditto85 Oct 23 '17 at 22:29
  • 1
    (7/3) - (4/3) is (3/3) obtained through "weird" floating points numbers that cant be represented properly ... which -1 should give us the difference ... I guess? – sbditto85 Oct 23 '17 at 22:39
  • Sure, see problem 3 of here: http://rstudio-pubs-static.s3.amazonaws.com/13303_daf1916bee714161ac78d3318de808a9.html – Moustache Oct 24 '17 at 10:43
  • or here: https://stackoverflow.com/questions/19141432/python-numpy-machine-epsilon – Moustache Oct 24 '17 at 10:43
  • But in answer to your second comment, yes I think so. There are some exceptions though, I couldn't get it to work with native Python 3.6 floats (not numpy) as there seems to be some automatic rounding under the hood to correct for that exact type of floating point weirdness. Didn't have time to find the relevant Python documentation to check up on it. – Moustache Oct 24 '17 at 10:44
  • This expression only works in IEEE 754 binary floating point. It doesn't work in [decimal floating point](https://en.wikipedia.org/wiki/Decimal_floating_point), for example. – SGJ Jul 27 '18 at 16:27
  • @SGJ True, but as far as I'm aware decimal floating point types are not yet part of the Go language, and as I mentioned before there are exceptions in other programming languages. See this Github issue for more information: https://github.com/golang/go/issues/19787 in the case of Golang. I have updated answer to clarify. – Moustache Jul 27 '18 at 17:27
  • Also as a correction to my previous comment it does work in Python with native floats I was just doing integer division by mistake. Woops. – Moustache Jul 27 '18 at 17:42