Thanks you two for all the help, you've provided some good food for thought. I think ive improved on both your techniques though. See what you think.
So i did it using the mod way, which i think is better a) fast since it doesnt us a look up table b) allows a greater level of accuracy than jpl's method.
Basically the problem with jpls method is that 3.0 is rarely 3.0 but 2.999999999999999999999 (thanks IEEE) which works when (int)(2.99999 * 100.0) = 299 which will get you 3.0. However if you have 3.02499999 which should be 3.025, if you mult by 100 and floor it you get 302 which will round to 3.00 and not 3.05.
3.0265 --> 3.00 // wrong
3.0298 --> 3.00
3.0331 --> 3.05
So use round instead of floor i hear you cry. Well you get a different problem at the other end 2.9868 should round to 2.98 but 298.68 rounds to 299 which gives you 3.00
2.9835 --> 2.98
2.9868 --> 3.00 // wrong
2.9901 --> 3.00
So where is the solution? Well you just need to do it with floor and look at an extra decimal place i.e. scale up by 1000 not 100 and then do the floor and integer calc.
Here is the code anyways. (It assumes you use jpl's lookup table for tick size)
public double roundToNearestTick(double value) {
final double scaleup = 1000.0 ;
int iValue = (int)(value * scaleup);
int tickSize = (int) (getTickSize(value) * scaleup);
int remainder = iValue % tickSize;
if (remainder < (tickSize / 2.0)) return ((iValue - remainder) / scaleup);
else return ((iValue + (tickSize - remainder)) / scaleup);
}
Rounding is a bitch.