Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

math: math.Floor bugged on products of certain float64 numbers #41283

Closed
ghost opened this issue Sep 9, 2020 · 3 comments
Closed

math: math.Floor bugged on products of certain float64 numbers #41283

ghost opened this issue Sep 9, 2020 · 3 comments

Comments

@ghost
Copy link

ghost commented Sep 9, 2020

What version of Go are you using (go version)?

$ go version
go version go1.15 linux/amd64

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/h/.cache/go-build"
GOENV="/home/h/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/h/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/h/go"
GOPRIVATE=""
GOPROXY=""
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/h/Documents/go/abc/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build051312685=/tmp/go-build -gno-record-gcc-switches"

What did you do?

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

What did you expect to see?

A correct floor results.

What did you see instead?

When I tried to get the floor of 680.0*0.35, I got 237 instead of 238.

@chanxuehong
Copy link
Contributor

chanxuehong commented Sep 9, 2020

package main

import (
	"fmt"
)

func main() {
	var a, b float64 = 680, 0.35
	fmt.Println(a, b, a*b)
}

it prints

680 0.35 237.99999999999997

So I think 237 is correct

you can see https://en.wikipedia.org/wiki/IEEE_754

@beoran
Copy link

beoran commented Sep 9, 2020

680.0 * 0.35 = 680 * 35 / 100 = 23800 / 100 = 238. The floor result is correct.

On Ruby, this multiplication gives the incorrect result of 237.99999999999997.

I'm impressed that Go manages to get this right. But still, don't use floating point for exact calculations, such as calculations involving money.

EDIT:

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

package main

import (
	"fmt"
	"math"
)

func main() {
	var a float64 = 680.0 
	var b float64 = 0.35
	res := a * b
	fmt.Printf("%f, %f, %v %v %v\n", 
		res, 
		math.Floor(res),
		(res == 237.99999999999996), 
		(res > 237.99999999999995), 
		(res < 238.0),
	)
}

Prints 238.000000, 237.000000, true true true. So Go gets it wrong anyway. The conclusion stays the same, don't use floating point for exact math.

@randall77
Copy link
Contributor

This is not a bug. 0.35 is not exactly representable as a floating point number, so there will be rounding error. If that error is downwards, then taking the floor gets you the integer almost 1 lower than the product.

@golang golang locked and limited conversation to collaborators Sep 9, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants