Multiplying floats

Why is that when I multiply 0.9 and 9 do I get 8.099999? Both variables are set to floats, but this is the output I am getting when I know it should be 8.1! As you can see I am getting so frustrated!

float num1 = rand/10f;//divide by 10 to get a decimal value, i.e. - 2 = 0.2

float num2 = rand2;//random integer 1-9

float num3 = num1*num2;//multiplying the above two values

Thanks in advance,

M.

[432 byte] By [mmchenrya] at [2007-10-1 0:40:11]
# 1

Because IEEE-whatever-it-is floating point format can't store that particular value exactly. It's not a Java issue, it's a math issue, and it's present in all computer hardware and languages. Well, okay, all hardware and languages that have a finite number of digits in which to store floating point numbers.

Try this exercise: In binary, "0.1" means 1*(2^-1), in other words, 1/2, and "0.01" is 1/4, etc.

Now, try to write 1/10 (base-10) exactly in binary. (Here's a hint: It will take you an infinite amount of time to do so, no matter how fast you write.)

Bottom line: You've got a finite number of bits in which to represent an infinite number of values, so a whole buttload of values are going to be approximations. The ones that can be represented exactly aren't the same as those that can be represented exactly in an equivalent number of base-10 digits.

http://docs.sun.com/source/806-3568/ncg_goldberg.html

You can use BigDecimal if you want fixed-point math. Or you can round your result before displaying it.

jverda at 2007-7-8 0:53:16 > top of Java-index,Security,Event Handling...
# 2

Thank you so much! I have been spinning my wheels on this for days. After reading your post and realizing that was the problem it freed my brain to think of a different solution. What I ended up doing to correct this issue was to multiply the two integers then divide by ten to get the float value. I am not sure this is the best way to do it but it works so that is good enough for me.

Thanks

mmchenrya at 2007-7-8 0:53:16 > top of Java-index,Security,Event Handling...
# 3

> Thank you so much! I have been spinning my wheels on

> this for days. After reading your post and realizing

> that was the problem it freed my brain to think of a

> different solution. What I ended up doing to correct

> this issue was to multiply the two integers then

> divide by ten to get the float value. I am not sure

> this is the best way to do it but it works so that is

> good enough for me.

>

> Thanks

That approach is valid in some circumstances. If it works for you across the range of expected inputs, then run with it.

jverda at 2007-7-8 0:53:16 > top of Java-index,Security,Event Handling...
# 4

If what you want to do is print float or double numbers with a fixed

number of digits in the output, then you should use the java.text.DecimalFormat

class to do it:

http://java.sun.com/j2se/1.4.2/docs/api/java/text/DecimalFormat.html

Related reading:

Other than the JLS Sections

4.2.3 "Floating-Point Types, Formats, and Values" and

4.2.4 "Floating-Point Operations"

http://java.sun.com/docs/books/jls/second_edition/html/typesValues.doc.html

Some good bedtime reading follows:

[1] "FLOATING-POINT NUMBERS - GENERAL VIEW" A short writeup. (This

information holds true for any programming language)

http://www.ibiblio.org/pub/languages/fortran/ch4-1.html

[2] HIGHLY recommended: David Goldberg, "What Every Computer Scientist

Should Know About Floating-Point Arithmetic", ACM Computing Surveys,

Vol. 23, No. 1, March 1991, pp. 5-48.

http://docs.sun.com/source/806-3568/ncg_goldberg.html#674

[3] Also highly recommended: Numerical Computation Guide

http://docs.sun.com/source/806-3568/index.html

timbella at 2007-7-8 0:53:16 > top of Java-index,Security,Event Handling...
# 5

Float numbers are never treated as expected in computers

if you want to test your result you should not say var == 8.1 but test a range instead: var >= 8.09 || var <= 8.11 ... or use absolute numbers for convenience: Math.abs(var - 8.1) <= 0.1

But in these cases I use a different approach. I usually care only for 2 or 3 digits of decimal precision so I simply multiply the numbers by 1000 and use integers to multiply and divide

So I write a float 8.1 as an integer 8100. It a lot more stable to test var == 8100 where var is an integer, rather than var == 8.1 where var is a float. And then you can easily divide 8100 by 1000 to get it back to the floating form.

sunlnka at 2007-7-8 0:53:16 > top of Java-index,Security,Event Handling...
# 6

Thank you timbell for the suggested reading. I looked at using the DecimalFormat, but since I had numbers such as (8.099999), this would not work. I also tried using BigDecimal w/ round_up, and it would give me 1.000005 as 1.1. Since these were not what I was looking for I instead did the multiplication with the integers then convert to a float.

Thanks,

M

mmchenrya at 2007-7-8 0:53:16 > top of Java-index,Security,Event Handling...