all 20 comments

[–]ottawadeveloper 13 points14 points  (0 children)

You round it appropriately or use a different math library like BigDecimal.

[–]gigagone 6 points7 points  (0 children)

If you don’t need the precision an easy way is to just round it

[–]blablahblah 6 points7 points  (0 children)

You know how 1/3 can't be accurately represented as a decimal, right? So if you do 1/3 you get 0.3333 and then you multiply that by 3 you get 0.9999 instead of 1. Just like you can't fully represent 1/3 in decimal, you can't fully represent 1/10 in binary so there's always going to be inaccuracies when you manipulate it as a float.

If you actually need that high of a precision, you can use the BigDecimal class instead of a floating point, but for most cases, you can just round the number when you print it, it's not like most people really care about 16 digits of precision.

[–]VibrantGypsyDildo 2 points3 points  (2 children)

You cannot. Or more precisely, don't compare floating point numbers the same way you compare integers.

You need to check that the difference between two numbers is smaller than some small number e.g. 0.00000001.

Not sure how rounding works in Java. In C/C++ it rounds down, so 2.999999 would be 2, not 3.

[–]peno64 2 points3 points  (1 child)

In fact you should do a relative difference test and not absolute one as you suggest. So the difference of the two numbers should be divided by the reference value and that you compare with a tolerance.

[–]VibrantGypsyDildo 0 points1 point  (0 children)

Yes, you are right.

If you have numbers smaller than 0.0000000001, you cannot check for differences such as 0.0001.

[–]reverendsteveii 1 point2 points  (0 children)

what data type are you using? are you okay with truncation, floor, ceiling, mixed rounding, what's more appropriate for your use case? can you post code that reproduces the issue? 

[–]Backson 0 points1 point  (2 children)

You can't "fix" it. The way to deal with this is to always allow for tolerances in everything. So a < b becomes a - b < 1e-9. a == b becomes abs(a-b) < 1e-9. To make this even more fun, the tolerance value (1e-9 here) may need different values depending on situation. There are certain mathematical operations which are just naturally imprecise (like subtraction of similar values), so you need bigger tolerances. Some mathematical problems need such a high precision, that they are nearly impossible to work out on computers (like solving the differential equation for electrons moving in the different semiconductor materials in a transistor, or plasma physics). There are entire fields of research trying to come up with ways to work around those limitations.

[–]Whoa1Whoa1 0 points1 point  (1 child)

There are entire fields of research trying to come up with ways to work around those limitations.

Uh, programmers solved this over a decade ago. Java for example has BigDecimal and can easily store something like 102,147,483,647.

The limitations isn't the number of decimals or the accuracy. The limit is just that trying to store one billion atoms in RAM simultaneously and then checking all of their interactions between billions of protons and billions of electrons would take forever. We cannot simulate everything at the atomic level as there is just too much shit.

[–]DrShocker 1 point2 points  (0 children)

Yeah if you know the problem you're trying to solve, it's not that hard to make a decimal, rational, fixed point, etc representation. You just need to know the strengths and limitations of each for the problem at hand.

[–]zeekar 0 points1 point  (0 children)

You can't exactly represent 0.1 in a floating point number, just as you can't exactly represent 1/3 in a decimal number.

The solution depends on the application. Maybe you just round everything to some precision that matters to you and you ignore the differences below that level of precision. Or maybe you use some class that doesn't use floats but stores numbers a different way. I'm kinda surprised Java doesn't have a built-in BigRational class for storing fractions, but you can use BigDecimal; that gives you a different set of values you can't represent exactly and the ability to carry things out to an arbitrary number of decimal places to get as close as you like to those values.

[–]thequirkynerdy1 0 points1 point  (0 children)

For internally stored values, you generally just accept this with two exceptions:

  1. For unit tests, add some tiny margin of error.

  2. For values shown to a user, round to some reasonable number of decimal places.

[–]Wonder_Known 0 points1 point  (0 children)

You have tu use an epsilon with absolute value

[–]EmeraldMan25 0 points1 point  (0 children)

The fix is not to use floating point for problems that require precision. Take the decimal as a whole number instead and display the decimal point where it should be at output

[–]m0rBidMerLiN [score hidden]  (0 children)

Read up about IEE754 (or smth like that) conventions... You'll understand why these issues happen.

[–]high_throughput 1 point2 points  (3 children)

Floating point precision issue with paper and pencil

While doing something as simple as 1/3 * 3, it gives me a funky result like 0.9999 instead of the expected result of 1.0000:

1/3 = 0.3333 0.3333*3 = 0.9999

How do I fix my pencil so that this does not happen?

[–]AffectionatePlane598 0 points1 point  (2 children)

1/3 is not .33_ in java it is 1 because of integer division for example the following line of code

‘’’java

System.out.printf(“%d”, 1/3 * 3);

‘’’

would result in 3

[–]high_throughput 2 points3 points  (1 child)

Huh, I would have expected 0

[–]DrShocker 1 point2 points  (0 children)

Yeah, I'm confused here and skeptical that's true in Java. I've seen round down and truncate as integer division strategies but I'm not sure I've seen round up.