#1026 Float and bugs

Akcelisto Mon 15 Mar 2010

class TestFloat{
  static Void main(){
    if(0F/0F==Float.nan){        
      echo("ok")
    } else{
      echo("not ok")
    }    

    if(Float.nan==Float.nan){        
      echo("ok")
    } else{
      echo("not ok")
    } 

    f := Float.posInf    
    echo(f)
    echo("$f")
  }
}

Output:

not ok
not ok
Infinity
INF  

Expected:

ok
ok
INF
INF  

brian Mon 15 Mar 2010

Fantom uses same conventions are Java where NaN is not equal to NaN. Its weird, but that is just the way Java does floating point comparisons.

The infinity thing is weird - I expect that is just an agressive const folding not working exactly right.

tactics Mon 15 Mar 2010

In the docs, it says that NaN is equal to itself, unlike Java:

http://fantom.org/doc/sys/Float.html

override Int compare(Obj obj)

Overrides sys::Obj.compare

Compare based on floating point value.

NaN works as follows:

    * for the <=> operator NaN is always less than other values and equal to itself (so sort works as expected)
    * for all other comparison operators anything compared against NaN is false (normal Java semanatics)

.

override Bool equals(Obj? obj)

Overrides sys::Obj.equals

Return true if same float value. Unlike Java, NaN equals NaN.

KevinKelley Mon 15 Mar 2010

the way Java does floating point

Heh. I especially like the phrase in JLS :

The floating-point types ... which are conceptually associated with IEEE754

"conceptually associated." Anyway, good overview of Java float pitfalls is Brian Goetz

... It occurs to me though, that sys::Float is missing an api: a NaN doesn't equal anything, including another NaN; so to identify one, Java gives the static Float.isNaN method, which I now notice we don't have.

NaN is not equal to NaN.

That should be true, but in fansh:

Fantom Shell v1.0.51.1 ('?' for help)
fansh> f := 0f/0f
NaN
fansh> g := 0f/0f
NaN
fansh> f==g
true

NaN really shouldn't ever equal anything, but looks like we're not doing that, and the doc for sys::Float.compare seems to agree.

There's always the old Knuth chestnut about those who use floating-point to calculate "real" numbers are living in a state of sin...

Akcelisto Mon 15 Mar 2010

How to check float is not real?

Now I write that:

Float f := ...
if(f.toStr=="NaN" || f.toStr=="INF" || f.toStr=="-INF"){
  echo("f is not real")
}

tactics Mon 15 Mar 2010

That would be a really nice convenience method to have: Float.isReal() or Float.isFinite() or whatnot.

brian Mon 15 Mar 2010

The equals doc was a mistake, left over from before we make Float a Java double.

The compare docs are correct, which means you can use <=> to check for NaN equality:

fansh> Float.nan == Float.nan
false
fansh> Float.nan <=> Float.nan
0

I also pushed a fix for the echo problem - it correctly prints "INF" now in all cases.

tactics Mon 15 Mar 2010

left over from before we make Float a Java double.

Does that mean that the behavior of Floats are necessarily platform dependent in Fantom?

It's probably not all that important since Decimal is the "default" floating point type.

brian Mon 15 Mar 2010

Does that mean that the behavior of Floats are necessarily platform dependent in Fantom?

No the test suite dictates the required behavior, which is also for .Net and JavaScript (or should be). I am pretty sure those are standard IEEE rules.

Login or Signup to reply.