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

spec: typed floating point constant does not match compiler behaviour #4398

Closed
ianlancetaylor opened this issue Nov 16, 2012 · 9 comments
Closed
Milestone

Comments

@ianlancetaylor
Copy link
Contributor

Is this a valid program?

package main

import "fmt"

const x1 = 1 - float64(1.00000000000000000001)
const x2 = float64(1 - 1.00000000000000000001)

func main() {
    fmt.Println(x1)
    fmt.Println(x2)
}

The spec says that a constant value x can be converted to type T if "x is
representable by a value of type T."  The value 1.00000000000000000001 is not
representable in float64; the closest approximation is 1.

Neither compiler actually behaves this way.  The two compilers produce different results
for the above program.  The gc compiler rounds the value before computing the
subtraction for x1; gccgo does not.  Probably the gc compiler is correct, but the spec
does not support either choice.

We probably do not want to take the spec too seriously, because it would mean that,
e.g., float64(math.Pi) would be invalid.  The spec should probably say that converting a
constant to a floating point value permits dropping the least significant bits.

The correct implementation of the above program will then hinge on the meaning of
"typed constant," a term that the spec does not clearly describe.
@DanielMorsing
Copy link
Contributor

Comment 1:

I don't think the spec says typed constant, but it does talk about giving constants a
type.
Quoting from the section on constants: "A constant may be given a type explicitly by a
constant declaration or conversion, or implicitly when used in a variable declaration or
an assignment or as an operand in an expression."
The section about conversions only mention that the constant must be able to be
represented by the type converted to. I say that a caveat be added about the LSBs on
floating point types here.

@extemporalgenome
Copy link
Contributor

Comment 2:

const x = 4.0 / 3
const y float64 = x
In this case, I believe iant's interpretation of the spec would require that compilation
not continue, since any finite amount of binary floating point precision could not
exactly represent that value. Judicious use of "closest representable approximation" for
floats may simplify the wording.

@griesemer
Copy link
Contributor

Comment 3:

There are two separate issues:
1) What does it mean for a floating point constant x to be representable by a type T?
2) What does it mean for a floating point constant x to be typed (via a conversion) -
specifically, what happens to the constant value.
2) is different from 1) because if T(x) is valid (x is representable by T) and thus x
gets "typed" as T, the (compile-time precise) value of x doesn't necessarily need to
change. For instance, float32(2.0/3.0), is a typed floating point constant (type is
float32), but it could still have the precise value 2.0/3.0 (rather than the "truncated"
value that fits into a 32bit float32).
I agree that the spec needs to be clearer with respect to these terms.

@rsc
Copy link
Contributor

rsc commented Nov 19, 2012

Comment 4:

In the gc compilers, I treat the constant conversion float64(x) as
meaning 'get me an exact float64 for x'. I hope this is in the spec
but haven't checked. That explains the gc behavior you saw.
It is true that we are a bit fuzzy about 'representable'. I interpret
it to mean that rounding is okay but completely out of range values
are not (i.e. 1e500 is not representable: it does not round to 1e308
nor does it round to +inf).

@rsc
Copy link
Contributor

rsc commented Dec 10, 2012

Comment 5:

I believe Ian made gccgo match the gc compilers. Perhaps we should do the same in the
spec?
I.e. a constant conversion to a floating-point or complex type rounds the constant value
to the nearest constant value exactly representable by that type.

@rsc
Copy link
Contributor

rsc commented Dec 10, 2012

Comment 6:

Labels changed: added size-m.

@rsc
Copy link
Contributor

rsc commented Jan 31, 2013

Comment 7:

Labels changed: added priority-later, removed priority-soon.

@rsc
Copy link
Contributor

rsc commented Feb 9, 2013

Comment 8:

Owner changed to ---.

Status changed to Started.

@rsc
Copy link
Contributor

rsc commented Feb 11, 2013

Comment 9:

This issue was closed by revision 7576179.

Status changed to Fixed.

@rsc rsc added this to the Go1.1 milestone Apr 14, 2015
@rsc rsc removed the go1.1 label Apr 14, 2015
@golang golang locked and limited conversation to collaborators Jun 24, 2016
This issue was closed.
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

6 participants