Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Floor(X) modulo X equals X?

Tags:

java

quick question. I'm basically working on a program where we have an Entity cross across a grid. Every time it finishes a "step" (ie, goes from (0, 0) to (1, 0)), I need to fire off an event. The entity's movement per frame is calculated by:

frameMovement = entitySpeed * (frameDeltaMs / 1000)

and then added onto the entity's X co-ordinate. I elected to use world units (1 world unit is 16 pixels) instead of raw pixels for the co-ordinate system simply for separation of concern. The world does not need to know that the distance for one square is 16 pixels - only the drawing system does.

So basically, I'm trying to work out how to tell the system that the unit has finished a "step". Obviously, due to the way the frame movement is calculated, you will never be exactly on a new square, so I must "clip" the unit to that square or have a method that will return "true" if we are within a certain distance from the square (which right now I have decided to be 0.05wu - about 0.8 pixels from the square).

The function I have so far is this:

return Math.floor(x) % x == 0;

I'm only using X seeing as I'm just trying to get it working at the moment. However the problem I have is that this function seems to return one of two results:

x = 0f;
System.out.println(Math.floor(x) % x);
> NaN

This is to be expected, as 0 % 0 is indeed NaN. I can work around this no problem. However the issue I have at the moment is the other result..

x = 1f; // Or any number with 1sd > 0
System.out.println(Math.floor(x) % x);
> 1f

That is, the other result always returns the value of X, rather than the correct modulo (which, if math.floor(x) and x are equal - ie x is equal to 1f), which should be 0.

I'm not entirely sure what is causing this. If you have any answers for me or any suggestions on how I can fix this in a better way, I'm all ears.

TL;DR: I need to figure out when an Entity moves from one co-ordinate to the next. The co-ordinates (and the Entity's transition across them) are stored as a float. If an Entity is halfway across traversing a square, the Entity's X co-ordinate is stored as 1.5, for example. Finally, Floor(1.0) % 1.0 is returning 1.0, and not 0.

EDIT:

In my code I have this

    System.out.println("x equals " + x + ". Math.floor(x)%x==Math.floor(x): "+(Math.floor(x)%x==Math.floor(x)));

With output http://pastebin.com/egDwj7Gs

EDIT 2: Images are fun!

http://prntscr.com/1j193n

The white square is the entity. The red square is simply a drawn-on grid. Each square is 16 by 16.

As you can see, right now the white square is at (6.5, 0). I need the program to basically recognise when it passes (7, 0).

EDIT: Lee and I had a chat, here's our chat: https://chat.stackoverflow.com/rooms/34727/discussion-between-neglected-and-lee-meador

He solved the problem for me so I have accepted his answer as correct.

        float after = pos.x+changeInPosition;

        if (Math.floor(after) != Math.floor(pos.x)) {
            // We passed a boundary
        }
        pos.x = after;
like image 507
Dan Avatar asked Aug 02 '13 20:08

Dan


1 Answers

Modulo means we divide and take the remainder (just like in 3rd grade for me).

So ...

10 % 9 is 1.

And

10 % 10 is 0

And

10.5 % 10.5 is 0. 

(Perhaps you could get rounding issues if you had x = ...calculate 10.5.. and then x % x where you would get a number just below 10.5 or just larger than 0.)

So, for all integers,

Floor(x) % x is 0.

For a non-integer, it works differently.

Floor(10.5) => 10 

and

10 % 10.5 is 10.

So barring the effect of rounding errors in the floating point, Floor(x) % x is either 0 (for integers) or Floor(x) for non-integers.

More

Perhaps you could tell if it passed a grid line by comparing the before and after positions:

if (Math.Floor(xAfterMoving / gridSize) != Math.floor(xBeforeMoving / gridSize)) {
    fireXGridCrossingEvent();
}
like image 183
Lee Meador Avatar answered Nov 03 '22 19:11

Lee Meador