2

Let me further explain my question. Let's say my Velocity is at -5.4028000 I would love it to return to zero like so.

-5.4,
-5.3,
-5.2
... 
-0.2,
-0.1,
0

Same with positive numbers. For them to return to 0, In groups of 0.1's. It would return to 0, every time it was run. Because this will be placed in a update loop.

Things I have tried:

if(vx > 0)
{
    vx-=0.1;
}
if(vx < 0)
{
    vx+=0.1;
}

But this just locks my VX into:

VX:0.04999999

OR

VX:0.09999999

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523

3 Answers3

4

The reason your number does not return back to zero is that the last subtraction may be subtracting a wrong number due to rounding errors. Since neither 5.4 nor 0.1 can be represented precisely in the format of double, your last subtraction (or your last addition in case of negative numbers) would "overshoot".

This is a problem for Math.min(...) and Math.max(...). Basically, we're going to only add or subtract the exact amount we need to reach zero.

if (vx > 0) {
    vx -= Math.min(0.1, vx);
}
if (vx < 0) {
    vx += Math.min(0.1, -vx);
}
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
Ben M.
  • 2,370
  • 1
  • 15
  • 23
  • Thank-you! This works amazing! And it is actually running very fast. – Maydon Game Studios Sep 14 '15 at 16:18
  • Won't work in the second case though - consider, if vx = -0.05 then Math.max(0.1, -0.05) will be 0.1. So, vx would become 0.05 and then get decremented by the first "if" next time round . – BarrySW19 Sep 14 '15 at 16:21
  • @BarrySW19 This is fixed now. – Sergey Kalinichenko Sep 14 '15 at 16:21
  • @dasblinkenlight Thanks for the fix. – Ben M. Sep 14 '15 at 16:23
  • 1
    You can do it branch free using `vx -= Math.copySign(Math.min(0.1, Math.abs(vx)), vx);`… – Holger Sep 14 '15 at 16:32
  • For some reason @Holger your answer, actually works faster and smoother. – Maydon Game Studios Sep 14 '15 at 16:44
  • Couldn't this still get into the situation where imprecise doubles and double arithmetic makes it oscillate between two values? This is more of a bandaid and only works with the exact value of `.1`. Really, I think you want to set `vx=0` if `vx < .1` not do more substraction. (I mean with a different double value than .1) – Carlos Bribiescas Sep 14 '15 at 16:52
  • @MaydonGameStudios Is it because you should use `else if` instead of `if`? – Carlos Bribiescas Sep 14 '15 at 16:57
  • @CarlosBribiescas You're making good points, but it's already been accepted as the answer so I don't want to make edits. I think I would edit it to use `else`, or even change it completely to just explicitly set the value to 0 if it's within the range `-0.1 < vx < 0.1`. – Ben M. Sep 14 '15 at 16:59
  • @BenM. Hah, very true. I wouldn't want to lose those 15 points either. :-) – Carlos Bribiescas Sep 14 '15 at 17:26
0

You need to make sure the final increment/decrement is not greater than the magnitude of the number:

if(vx > 0) {
    vx -= Math.min(0.1, vx);
}
if(vx < 0) {
    vx += Math.min(0.1, Math.abs(vx));
}
BarrySW19
  • 3,759
  • 12
  • 26
-1

Well assuming you want a change rate of 0.1 per second and do not use any fancy library, you could do something like this:

while (Math.abs(vx) - 0.1 > 0.0) {
    vx += -Math.signum(vx) * 0.1
    Thread.sleep(1000)
}
vx = 0.0;
Sascha Kolberg
  • 7,092
  • 1
  • 31
  • 37