11

IEEE754 supports the negative zero. But this code

a  := -0.0
fmt.Println(a, 1/a)

outputs

0 +Inf

where I would have expected

-0 -Inf

Other languages whose float format is based on IEEE754 let you create negative zero literals

Java :

float a = -0f;
System.out.printf("%f %f", a, 1/a); // outputs "-0,000000 -Infinity"

C# :

var a = -0d;
Console.WriteLine(1/a); // outputs "-Infinity"

Javascript :

​var a = -0;
console.log(a, 1/a);​ // logs "0 -Infinity"

But I couldn't find the equivalent in Go.

How do you write a negative zero literal in go ?

Denys Séguret
  • 372,613
  • 87
  • 782
  • 758

3 Answers3

11

There is a registered issue.

And it happens to give a kind of solution :

a := math.Copysign(0, -1)

It's not so bad as it obviously refers to the standard copysign function defined by IEEE754.

But this means you need to import a package and this still looks much too heavy for the (admittedly minor and rare) need.

Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
  • W/o importing "math": http://play.golang.org/p/iymSJElses (and it gets inlined, I belive) – zzzz Dec 10 '12 at 16:24
  • 8
    It's unfortunate that this seems to be the specified language behavior (from the discussion on the issue page), as it clearly contravenes IEEE-754 (5.12.1) "The conversions from supported formats to external character sequences [which includes source-language literals] and back that recover the original floating-point representation, shall recover zeros, infinities, and quiet NaNs, as well as non-zero finite numbers. **In particular, signs of zeros and infinities are preserved.**" – Stephen Canon Dec 10 '12 at 17:31
6
package main

import (
        "fmt"
        "math"
)

func main() {
        a := 1. / math.Inf(-1)
        fmt.Println(a, 1/a)
}

(Also here)


Output:

-0 -Inf
zzzz
  • 87,403
  • 16
  • 175
  • 139
  • OK. It answers (hence +1). But seriously why not `a := -0.0` similarly to other languages ? Is that a bug or a "feature" ? – Denys Séguret Dec 10 '12 at 15:52
  • Mathematically -0 and 0 are equal, so I guess Go does the right thing. The signedness of 0 is, AFAIK, only a result of an underflow, not from an unary minus (like -1*0). – zzzz Dec 10 '12 at 16:03
  • They're "equal" as -0==0 should give true, but in other languages (I just tested in Javascript and in Java), dividing 1 by -0 or +0 gives -Infinity or +Infinity. And this can be important. – Denys Séguret Dec 10 '12 at 16:07
  • It might be the case that Javascript and Java don't do the "right thing". K.T./R.P./M.J./... would be helpful in this, I believe. I suggest to ask again at the mailing list ;-) – zzzz Dec 10 '12 at 16:10
  • 1
    Please don't compare to Javascript. JS is renowned for getting many things wrong in maths. – JohnDoe Dec 10 '12 at 16:12
  • Maybe but the negative zero is a basic property of IEEE754 and I don't see how JS is wrong there. And it's handled in Go, the problem seem to arise from constants. – Denys Séguret Dec 10 '12 at 16:14
  • 3
    @jnml - it's not quite correct that +0 == -0 because "−0" might denote a small negative number that has been rounded to zero. http://en.wikipedia.org/wiki/Signed_zero. Note that Go is claimed to handle IEEE-754 correctly and this is one of its requirements. – Rick-777 Dec 11 '12 at 10:05
  • @Rick-777 From the link you provide : *"According to the IEEE 754 standard, negative zero and positive zero should compare as equal with the usual (numerical) comparison operators, like the == operators of C and Java."* – Denys Séguret Dec 11 '12 at 13:05
  • As far as the comparison "==" is concerned, you are quite correct. My point is that limits and rounding issues has meant IEEE-754 needed to differentiate between +0 and -0 as an admission of the slight inexactitude of 2s-complement binary floating point arithmetic. – Rick-777 Dec 11 '12 at 13:27
0

I just tried out this and it seems to work for me .

package main

import (
    "fmt"
    )

func main() {
    zero := float64(0)
    neg_zero := -zero
    fmt.Println(zero, neg_zero)
}

Though it does not work as expected when I do neg_zer0 := - float64(0)

gprasant
  • 15,589
  • 9
  • 43
  • 57