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]

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.
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
> 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.
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
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.
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