Adding two float values got strange result

P

Pietro Marrone

Hi, thie is my simple test case:

public class Main {

public static void main(String[] args) {
float a = 123.76f;
float b = 52.0f;

System.out.println(a + b);
System.out.println((float) a + b);
System.out.println((float) a + (float) b);
System.out.println((float) (a + b));
}
}

The results for all four System.out is the same, guess what?:
175.01001

Cuold anyone explein me why, at least a refer to rules explaining what
happens?

Regards
 
C

Chris Dollin

Pietro said:
Hi, thie is my simple test case:

public class Main {

public static void main(String[] args) {
float a = 123.76f;
float b = 52.0f;

System.out.println(a + b);
System.out.println((float) a + b);
System.out.println((float) a + (float) b);
System.out.println((float) (a + b));
}

}

The results for all four System.out is the same, guess what?:
175.01001

Cuold anyone explein me why, at least a refer to rules explaining what
happens?

Floating. Point. Numbers. Have. Limited. Precision. And. Are. Not.
Stored. As. Decimal. Values.
 
P

Pietro Marrone

Hi, thie is my simple test case:

public class Main {

public static void main(String[] args) {
float a = 123.76f;
float b = 52.0f;

System.out.println(a + b);
System.out.println((float) a + b);
System.out.println((float) a + (float) b);
System.out.println((float) (a + b));
}

}

The results for all four System.out is the same, guess what?:
175.01001

Cuold anyone explein me why, at least a refer to rules explaining what
happens?

Regards

Another wrong test case:
package it.test;


public class Main {

public static void main(String[] args) {
float a = (float)123.76;
float b = (float)52.0;

System.out.println(a + b);
System.out.println((float) a + b);
System.out.println((float) a + (float) b);
System.out.println((float) (a + b));
}
}

gives 175.76001, but unfortunetly neither this result is correct.

My JRE version is:
java version "1.5.0_11"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_11-b03)
Java HotSpot(TM) Client VM (build 1.5.0_11-b03, mixed mode)

My OS is: Windows XP Professional Version 2002 SP2

My Hardware is:
AMD Athlon 64 Processor 3500+

Regards
 
P

Pietro Marrone

Hi, thie is my simple test case:

public class Main {

public static void main(String[] args) {
float a = 123.76f;
float b = 52.0f;

System.out.println(a + b);
System.out.println((float) a + b);
System.out.println((float) a + (float) b);
System.out.println((float) (a + b));
}

}

The results for all four System.out is the same, guess what?:
175.01001

Cuold anyone explein me why, at least a refer to rules explaining what
happens?

Regards

It works if I declare primitive types as double.
iis it a strange causality or is a rule?

Regards
 
A

Andrew Thompson

Pietro Marrone wrote:
..
public class Main {

public static void main(String[] args) {
float a = 123.76f;
float b = 52.0f;

System.out.println(a + b);
System.out.println((float) a + b);
System.out.println((float) a + (float) b);
System.out.println((float) (a + b));
}
}

The results for all four System.out is the same, guess what?:
175.01001

The results I get here are..

175.76001
175.76001
175.76001
175.76001
Cuold anyone explein me why, at least a refer to rules explaining what
happens?

Buggy implementation?
Check the launch files here (not the
screenshot on the right).
<http://www.physci.org/jws/#jtest>
..what is your java.vm.version (1.6.0-b105
in the screenshot)?
 
P

Patricia Shanahan

Pietro said:
Hi, thie is my simple test case:

public class Main {

public static void main(String[] args) {
float a = 123.76f;
float b = 52.0f;

System.out.println(a + b);
System.out.println((float) a + b);
System.out.println((float) a + (float) b);
System.out.println((float) (a + b));
}
}

The results for all four System.out is the same, guess what?:
175.01001

Are you absolutely sure the program you posted got that result?

I ran it with result:

175.76001
175.76001
175.76001
175.76001

which is the same as Andrew got. All Java implementations should get the
same answer for the posted program.

Patricia
 
P

Patricia Shanahan

Pietro said:
Hi, thie is my simple test case:

public class Main {

public static void main(String[] args) {
float a = 123.76f;
float b = 52.0f;

System.out.println(a + b);
System.out.println((float) a + b);
System.out.println((float) a + (float) b);
System.out.println((float) (a + b));
}

}

The results for all four System.out is the same, guess what?:
175.01001

Cuold anyone explein me why, at least a refer to rules explaining what
happens?

Regards

Another wrong test case:
package it.test;


public class Main {

public static void main(String[] args) {
float a = (float)123.76;
float b = (float)52.0;

System.out.println(a + b);
System.out.println((float) a + b);
System.out.println((float) a + (float) b);
System.out.println((float) (a + b));
}
}

gives 175.76001, but unfortunetly neither this result is correct.

The result you report for this program matches the answer Andrew and I
got for the first program.

Java float and double each represent numbers in binary floating point.
Java float has, effectively, 24 significant bits, the equivalent of
about 7.2 decimal digits. You should expect rounding error in the 8th
significant decimal digit.

The rules are in the JLS, see
http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.2.3
the following section, and the sections they reference.

IEEE 32 bit float is almost always the wrong data type to use. It gives
up a lot of accuracy for halving the space required compared to double.
If you should be using a binary floating point type at all, you should
normally use double. The exception is if you are storing a large number
of values with low accuracy requirements, and have done the numerical
analysis to convince yourself that float is precise enough.

If you need the behavior you seem to expect, exact representation and
addition of decimal fractions, consider using BigDecimal.

Patricia
 
L

Lew

Pietro said:
public class Main {

public static void main(String[] args) {
float a = 123.76f;
float b = 52.0f;

System.out.println(a + b);
System.out.println((float) a + b);
System.out.println((float) a + (float) b);
System.out.println((float) (a + b));
}

}

The results for all four System.out is the same, guess what?:
175.01001

Cuold anyone explein me why, at least a refer to rules explaining what
happens?

Chris said:
Floating. Point. Numbers. Have. Limited. Precision. And. Are. Not.
Stored. As. Decimal. Values.

Why isn't numerical analysis part of developer training?

To the OP:
<http://developers.sun.com/sunstudio/numerics_index.html>

In particular:
<http://docs.sun.com/source/817-6702/ncg_goldberg.html>
 
C

Chris Dollin

Lew said:
Why isn't numerical analysis part of developer training?

Because it's a horribly complex and detailed subject, most of which
is irrelevant to most of what most developers do.

Some /basic awareness/ of the floaty bits of floating point should
be grafted into the brain of a putative developer, mind.

--
"It took a very long time, much longer than the most /Sector General/
generous estimates." - James White

Hewlett-Packard Limited registered office: Cain Road, Bracknell,
registered no: 690597 England Berks RG12 1HN
 
P

Patricia Shanahan

Pietro said:
Hi, thie is my simple test case:

public class Main {

public static void main(String[] args) {
float a = 123.76f;
float b = 52.0f;

System.out.println(a + b);
System.out.println((float) a + b);
System.out.println((float) a + (float) b);
System.out.println((float) (a + b));
}

}

The results for all four System.out is the same, guess what?:
175.01001

Cuold anyone explein me why, at least a refer to rules explaining what
happens?

Regards

It works if I declare primitive types as double.
iis it a strange causality or is a rule?

Regards

As a general rule, double gives a lot more precision than float, 53
significant bits instead of 24. However, the default Double.toString
conversion always produces enough decimal places to uniquely identify
the double value, so it can produce similar effects, just with longer
output. Of course, all of this is very dependent on the particular
numbers you pick.

If you strongly favor exact processing of decimal fractions, you should
use neither double nor float, but BigDecimal which is designed for that job.

Patricia
 
J

Joshua Cranmer

Lew said:
Why isn't numerical analysis part of developer training?


It used to be, back when CS was part of "Applied Mathematics." It also
doesn't help that it is pushed back until late in the mathematics track:
I'm taking it next year, *after* Multivariable Calculus and Linear
Algebra...
 
J

John W. Kennedy

Pietro said:
Hi, thie is my simple test case:

public class Main {

public static void main(String[] args) {
float a = 123.76f;
float b = 52.0f;

System.out.println(a + b);
System.out.println((float) a + b);
System.out.println((float) a + (float) b);
System.out.println((float) (a + b));
}

}

The results for all four System.out is the same, guess what?:
175.01001

Cuold anyone explein me why, at least a refer to rules explaining what
happens?

Regards

It works if I declare primitive types as double.
iis it a strange causality or is a rule?

It "works" with float, too. It just doesn't work in the way that you
expect it to.

Computers use binary arithmetic. Some computers have used binary
arithmetic since the early 1950s, and nearly all computers have used
binary arithmetic since the mid 1960s. If you have taken any kind of
computer programming course at all, you should bring a lawsuit against
the fool of a teacher who did not instruct you in this.

Do you remember how, with decimal fractions, you discovered that 1/3 +
1/3 + 1/3 added up to 0.99 instead of 1? Well, with binary fractions,
you have the same problem where 1/10 or 1/100 is involved. But for
purposes of science and engineering, binary arithmetic is just as
effective as decimal arithmetic, and faster and cheaper. The world is
not carved up into exact decimal fractions. Distances between points are
not always an exact number of millimeters. Masses of objects are not
always an exact number of grams. Time intervals are not always an exact
number of milliseconds.

Money, on the other hand, /is/ carved up into exact decimal fractions.
Therefore, when you are working with money, you should use the Java
BigDecimal class, instead of float or double. Dollars are always an
exact number of cents. Euros are always an exact number of eurocents.
Pounds are always an exact number of new pence. The considerable loss of
time involved in using BigDecimal is unimportant, because the
calculations involving money are far less intensive than the complex
problems in calculus that come up in science and engineering.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top