Reputation: 18521
In brief - I am having a hard time with the float left overs
(i.e. 10.00000123 instead of 10)
Here I go :
I need to generate list of floats with constant gap as follows (actually its a map , I need to retreive the object nut nevermind that)
List A: 0.25, 0.5, 0.75, 1, ...
or
List B: 0.01, 0.02, 0.03, 0.04, ...
every time I get a number and I round it to the neerest cell in the list.
lets say I get 0.051 to retreive a cell in list A - I return 0.05.
lets say I get 0.21 to retreive a cell in list B - I return 0.25.
So I started be doing this
float a = Math.round(Value / step) * step;
but than I get a lot of time 0.2500001 (float leftovers ) I need a smart way to round it .
Maybe by taking the number of digits after the dot and doing again
Math.round(Value / 100) * 100;?
Is there a smarter way? I tried doig this
final float factor = Math.round(1 / step);
final float value = (float) Math.round(value * factor) / factor;
but I sometimes have a list like this
List A: 10, 15 , 20, 25, 30, ...
and when I get 22 I retreive the cell of 20. the problem is that When I get a gap of 10
Math.round(1 / baseAssetStep)
returns 0 - and I get NaN
Upvotes: 3
Views: 2822
Reputation: 533520
Firstly, I would use double
or long
instead as these have much more digits of accuracy. If you really need to, use BigDecimal, but its pretty rare to find a real world situation where double
or long
would not do the job.
double d = 10.00000123;
double r = Math.round(d * 10000) / 10000.0;
or using long with fixed point precision.
long l = 100000; // the actual value * 10000
A common use case for fixed point precision is money. Instead of using dollars with double
use cents with long
or even int
instead.
Upvotes: 2
Reputation: 43391
In short, "these are not the numbers you're looking for."
Floating points are represented as binary fractional numbers, and some numbers that can be easily represented in base-10 (0.01, for instance) can't be represented with a finite number of binary digits. This is similar to how 1/3 is easy in base 3 (it's just 0.1), but requires an infinite number of digits in base 10 (0.333...).
If you tried to represent 1/3 with a finite number of digits in base 10, you'd get an approximation. Similarly, if you try to represent 1/10 with a finite number of digits in base 2 (which is what float
and double
do), you'll get an approximation, and similarly with 1/100. What you think is 0.01 in the code is actually a number that's very close, but not exactly equal to, 1/100.
There are many resources out there concerning floating points and the difficulty in working with them. http://floating-point-gui.de/ is a good place to start.
Upvotes: 1
Reputation: 381
you need a constant gap, so maybe try another solution. Take your gap, let's name it G. Draw a randow int - let's call it R, (if you know maximum number in your list you can draw it properly). Now the only thing to do would be R*G which will give you a number from your list - of course with some precision because this is inevitable using float - to print it just use format. You can also combine this with BigDecimal ;)
Upvotes: 0
Reputation: 55524
Use BigDecimal
instead of float
.
From the Java Tutorials of Primitive Data Types:
float: [...] This data type should never be used for precise values, such as currency. For that, you will need to use the java.math.BigDecimal class instead. Numbers and Strings covers BigDecimal and other useful classes provided by the Java platform.
Upvotes: 6