Rounding to zero from positive or negative numbers results in positive or negative zero.

600 views
Skip to first unread message

Ilya Orson

unread,
Apr 20, 2016, 12:18:22 AM4/20/16
to julia-users
Hello everyone!
I was wondering if the following behavior of round() has an special purpouse:

a = round(0.1)
0.0

b = round(-0.1)
-0.0

a == b
true

a === b
false

bits
(a)
"0000000000000000000000000000000000000000000000000000000000000000"


bits
(b)
"1000000000000000000000000000000000000000000000000000000000000000"

So the sign stays around...

I am using this rounded numbers as keys in a dictionary and julia can tell the difference.

For example, I expected something like this:
dict = [i => exp(i) for i in [a,b]]
Dict{Any,Any} with 1 entry:
 
0.0 => 1.0

but got this:
dict = [i => exp(i) for i in [a,b]]
Dict{Any,Any} with 2 entries:
 
0.0  => 1.0
 
-0.0 => 1.0

It is not a big problem really but I would like to know where can this behaviour come handy.

Cheers!

Jeffrey Sarnoff

unread,
Apr 20, 2016, 1:10:31 AM4/20/16
to julia-users
Hi,

You have discovered that IEEE standard floating point numbers have two distinct zeros: 0.0 and -0.0.  They compare `==` even though they are not `===`.  If you want to consider +0.0 and -0.0 to be the same, use `==` or `!=` not `===`  or `!==` when testing floating point values (the other comparisons <=, <, >=, > treat the two zeros as a single value).

Tamas Papp

unread,
Apr 20, 2016, 1:36:35 AM4/20/16
to julia...@googlegroups.com
This is not Julia-specific, but what the IEEE floating point standard
requires. One rationale, I guess, could be a form of sign preservation
(signbit(x)==signbit(round(x))), although of course abs(sign(-0.0))==0.

Negative zeros make some computations more convenient, but can also be
the source of subtle bugs (like the issue you ran into). It's one of
those things that is good to know about, but perhaps more of a nuisance
than a feature unless you are working with algorithms that exploit the
properties of the extended real line and you have really thought it
through. For an example of code that uses the extended real line
elegantly, look at DSYEVR in LAPACK.

Best,

Tamas

David P. Sanders

unread,
Apr 20, 2016, 3:48:56 AM4/20/16
to julia-users
You can avoid the problem using

round(Int, x)

Which returns the result as an integer. Integers do not have this situation (difference between +0.0 and -0.0)

Milan Bouchet-Valat

unread,
Apr 20, 2016, 5:52:34 AM4/20/16
to julia...@googlegroups.com
Le mardi 19 avril 2016 à 22:10 -0700, Jeffrey Sarnoff a écrit :
> Hi,
>
> You have discovered that IEEE standard floating point numbers have
> two distinct zeros: 0.0 and -0.0.  They compare `==` even though they
> are not `===`.  If you want to consider +0.0 and -0.0 to be the same,
> use `==` or `!=` not `===`  or `!==` when testing floating point
> values (the other comparisons <=, <, >=, > treat the two zeros as a
> single value).
There's actually an open issue about what to do with -0.0 and NaN in
Dicts: https://github.com/JuliaLang/julia/issues/9381

It turns out it's very hard to find a good solution.


Regards

Stefan Karpinski

unread,
Apr 20, 2016, 10:18:06 AM4/20/16
to Julia Users
IEEE has not made the programming language designer's life easy here.

Andrew Gibb

unread,
Apr 20, 2016, 11:46:16 AM4/20/16
to julia-users
On Wednesday, 20 April 2016 15:18:06 UTC+1, Stefan Karpinski wrote:
IEEE has not made the programming language designer's life easy here.

Perhaps it's a subtle attempt to incentivise more designers of mathematical programming languages into IEEE standards committees?!

 
Reply all
Reply to author
Forward
0 new messages