Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Java > Comparing floating point values in Java

Reply
Thread Tools

Comparing floating point values in Java

 
 
Philipp
Guest
Posts: n/a
 
      12-30-2006
Hello,
I'm aware of problems (rounding, NaN etc) when comparing floating point
values in computers.
In C++ this goes a bit further as you cannot compare with certitude
floating point numbers even if you have made exactly the same operations
on each of them (see eg:
http://www.parashift.com/c++-faq-lit...html#faq-29.18 )

My question: In Java, will unchanged values compare strictly true if equal?
Is it _guaranteed_ that the following code does output "true" on all JVMs?

Thanks for answers. Phil

example code:
public class Test {
public static void main(String[] args) {
float a = 1;
float b = 1;
System.out.println("a == b?: " + (a == b));
}
}
 
Reply With Quote
 
 
 
 
Lew
Guest
Posts: n/a
 
      12-30-2006
Philipp wrote:
> float a = 1;
> float b = 1;


Side note: consider explicitly setting float variables to float constants
rather than integer constants:

float a = 1.f;

This prevents conversion from being an issue.

Generally you can count on constants comparing equal if they represent the
same value. Generally you cannot count on calculated values equaling
differently-calculated values even were they mathematically equivalent given
infinite precision.

It makes a difference what values you wish to represent. Not all values are
precisely representable in limited-precision floating point.

Read
<http://docs.sun.com/source/806-3568/ncg_goldberg.html>
available as a PDF from
<http://www.physics.ohio-state.edu/~dws/grouplinks/floating_point_math.pdf>
among other places.

- Lew
 
Reply With Quote
 
 
 
 
Thomas Schodt
Guest
Posts: n/a
 
      12-30-2006
Philipp wrote:
> I'm aware of problems (rounding, NaN etc) when comparing floating point
> values in computers.


> In Java, will unchanged values compare strictly true if equal?
> Is it _guaranteed_ that the following code does output "true" on all JVMs?
>
> Thanks for answers. Phil
>
> example code:
> public class Test {
> public static void main(String[] args) {
> float a = 1;
> float b = 1;
> System.out.println("a == b?: " + (a == b));
> }
> }


I would suggest that
any JVM where it would output false
is probably non-compliant.

Your example may be somewhat lacking
as many scalar values
and many fractions where the denominator is a cardinal exponent of 2
correspond exactly
to a floating point representation.

Personally I like to think of floating point values
as representing bounded infinite sets of real values
(or not bounded - for positive and negative infinity).


There are some that take a dim view on the liberties Sun / Gosling took
in the way Java deals with IEEE754 values, eg.;
<http://www.cs.berkeley.edu/~wkahan/JAVAhurt.pdf>
 
Reply With Quote
 
Daniel Pitts
Guest
Posts: n/a
 
      12-30-2006

Philipp wrote:
> Hello,
> I'm aware of problems (rounding, NaN etc) when comparing floating point
> values in computers.
> In C++ this goes a bit further as you cannot compare with certitude
> floating point numbers even if you have made exactly the same operations
> on each of them (see eg:
> http://www.parashift.com/c++-faq-lit...html#faq-29.18 )
>
> My question: In Java, will unchanged values compare strictly true if equal?
> Is it _guaranteed_ that the following code does output "true" on all JVMs?
>
> Thanks for answers. Phil
>
> example code:
> public class Test {
> public static void main(String[] args) {
> float a = 1;
> float b = 1;
> System.out.println("a == b?: " + (a == b));
> }
> }


Look into StrictMath.

It might also be worthwhile to learn how to calculate error, and
compare signifigant figures only. If you only need a "probably equal",
then you can use a delta, eg:

public class FloatEquality {
public static boolean areEqual(float a, float b, float delta) {
return Math.abs(a - b) < delta;
}
public static float DELTA_F = 0.00000001f;
public static void main(String[] args) {
float a = 1f;
float b = 1f;
System.out.println("a == b?: " + areEqual(a, b, DELTA_F);
}
}

Hope this helps.

Daniel.

 
Reply With Quote
 
=?ISO-8859-1?Q?Arne_Vajh=F8j?=
Guest
Posts: n/a
 
      12-30-2006
Philipp wrote:
> I'm aware of problems (rounding, NaN etc) when comparing floating point
> values in computers.
> In C++ this goes a bit further as you cannot compare with certitude
> floating point numbers even if you have made exactly the same operations
> on each of them (see eg:
> http://www.parashift.com/c++-faq-lit...html#faq-29.18 )
>
> My question: In Java, will unchanged values compare strictly true if equal?
> Is it _guaranteed_ that the following code does output "true" on all JVMs?


> example code:
> public class Test {
> public static void main(String[] args) {
> float a = 1;
> float b = 1;
> System.out.println("a == b?: " + (a == b));
> }
> }


Most C++ implementations use IEEE floating point.

Java uses IEEE floating point.

You should expect the same floating point issues in
Java as in C++.

Your example is not equivalent to the example in your link.

I believe that the above should always write true in Java.

But in general you should not use == to compare floating
points in Java either.

Your example are just more simple than real life code.

Arne



 
Reply With Quote
 
Philipp
Guest
Posts: n/a
 
      12-30-2006
Arne Vajhøj wrote:
> Philipp wrote:
>> I'm aware of problems (rounding, NaN etc) when comparing floating
>> point values in computers.
>> In C++ this goes a bit further as you cannot compare with certitude
>> floating point numbers even if you have made exactly the same
>> operations on each of them (see eg:
>> http://www.parashift.com/c++-faq-lit...html#faq-29.18 )
>>
>> My question: In Java, will unchanged values compare strictly true if
>> equal?
>> Is it _guaranteed_ that the following code does output "true" on all
>> JVMs?

>
>> example code:
>> public class Test {
>> public static void main(String[] args) {
>> float a = 1;
>> float b = 1;
>> System.out.println("a == b?: " + (a == b));
>> }
>> }

>
> Your example is not equivalent to the example in your link.


Yes I'm aware of that. The point in the link is that compiler
optimization can lead to unequal floats even if exactly the same
operations were performed on it. Is this also true for Java?

> But in general you should not use == to compare floating
> points in Java either.


Agree

> Your example are just more simple than real life code.


No! (If I ask the question it's because I met this problem)

I was calculating an array of float values from some user input. But
sometimes (rarely) the calculation cannot be done (this is correct
behavior).
I then want to mark these values by setting them to -1 and treat this
special case later on. So I later need to test for -1 in my array.

Philipp
 
Reply With Quote
 
Patricia Shanahan
Guest
Posts: n/a
 
      12-30-2006
Philipp wrote:
> Hello,
> I'm aware of problems (rounding, NaN etc) when comparing floating point
> values in computers.
> In C++ this goes a bit further as you cannot compare with certitude
> floating point numbers even if you have made exactly the same operations
> on each of them (see eg:
> http://www.parashift.com/c++-faq-lit...html#faq-29.18 )
>
> My question: In Java, will unchanged values compare strictly true if equal?
> Is it _guaranteed_ that the following code does output "true" on all JVMs?
>
> Thanks for answers. Phil
>
> example code:
> public class Test {
> public static void main(String[] args) {
> float a = 1;
> float b = 1;
> System.out.println("a == b?: " + (a == b));
> }
> }


Java does not permit reordering optimizations that could affect a
floating point result.

In strictfp mode, the exact, bit-by-bit, result is predictable from the
source code for any Java implementation.

Without strictfp, the implementation is allowed, but never required, to
use a wider exponent for some intermediate results. That may suppress an
overflow to infinity or underflow to zero (for numbers too tiny to be
represented as denormalized with the correct exponent width).

That would allow some calculations to get different results depending on
issues such as whether a value was kept in a register or stored to a
memory temporary.

If you are just concerned about issues such as whether Java will
arbitrarily reorder expressions, you are fine in default mode. If you
really need exact equality on every identical source calculation, you
need strictfp.

Patricia
 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      12-30-2006
Philipp wrote:
> [...]
>
> I was calculating an array of float values from some user input. But
> sometimes (rarely) the calculation cannot be done (this is correct
> behavior).
> I then want to mark these values by setting them to -1 and treat this
> special case later on. So I later need to test for -1 in my array.


Perhaps you can avoid the entire issue by choosing a
different "distinguished value." Float.NaN, maybe, using
the Float.isNaN(float) method instead of an == test. (NaN
seems a more natural surrogate for "does not compute," too.)

--
Eric Sosman
lid
 
Reply With Quote
 
Daniel Pitts
Guest
Posts: n/a
 
      12-31-2006

Eric Sosman wrote:
> Philipp wrote:
> > [...]
> >
> > I was calculating an array of float values from some user input. But
> > sometimes (rarely) the calculation cannot be done (this is correct
> > behavior).
> > I then want to mark these values by setting them to -1 and treat this
> > special case later on. So I later need to test for -1 in my array.

>
> Perhaps you can avoid the entire issue by choosing a
> different "distinguished value." Float.NaN, maybe, using
> the Float.isNaN(float) method instead of an == test. (NaN
> seems a more natural surrogate for "does not compute," too.)
>
> --
> Eric Sosman
> lid


Or even have a seperate boolean array to specify valid results.
Having a magic value isn't generally a good idea, although NaN would be
the way to go if you did.

 
Reply With Quote
 
Patricia Shanahan
Guest
Posts: n/a
 
      12-31-2006
Daniel Pitts wrote:
> Eric Sosman wrote:
>> Philipp wrote:
>>> [...]
>>>
>>> I was calculating an array of float values from some user input. But
>>> sometimes (rarely) the calculation cannot be done (this is correct
>>> behavior).
>>> I then want to mark these values by setting them to -1 and treat this
>>> special case later on. So I later need to test for -1 in my array.

>> Perhaps you can avoid the entire issue by choosing a
>> different "distinguished value." Float.NaN, maybe, using
>> the Float.isNaN(float) method instead of an == test. (NaN
>> seems a more natural surrogate for "does not compute," too.)
>>
>> --
>> Eric Sosman
>> lid

>
> Or even have a seperate boolean array to specify valid results.
> Having a magic value isn't generally a good idea, although NaN would be
> the way to go if you did.
>


Since the special cases are rare, one could also describe them by having
e.g. a HashSet<Integer> containing the index values of the special cases.

Using any magic value, including NaN, has the risk that a bug elsewhere
in the code will get hidden as the special case. The risk can be reduced
by using a specific NaN value and Float.floatToRawIntBits to check for it.

Patricia
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
comparing floating point numbers Adam Majewski C++ 12 02-13-2012 01:59 AM
Share-Point-2010 ,Share-Point -2010 Training , Share-point-2010Hyderabad , Share-point-2010 Institute Saraswati lakki ASP .Net 0 01-06-2012 06:39 AM
Comparing floating point numbers nw C++ 14 05-02-2007 02:47 PM
floating point problem... floating indeed :( teeshift Ruby 2 12-01-2006 01:16 AM
comparing floating point numbers Thens Perl Misc 3 07-10-2003 04:52 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57