|
Rounding down |
xinco1
Member #8,061
December 2006
|
Whats the best way of rounding a variable down to the nearest number. For example, if a variable is 99, and I want to round it to a multiple of 32, so the 99 variable is now 96. How do I do this? |
mscava
Member #6,815
January 2006
|
I have to be tired today... |
Matthew Leverton
Supreme Loser
January 1999
|
x = (x/32) * 32; // or x -= (x % 32)
|
Andrei Ellman
Member #3,434
April 2003
|
Matthew Leverton said:
x = (x/32) * 32; // or x -= (x % 32)
As 32 is a power of two, the above could be written x = (x>>5)<<5; // or x &= 0xFFFFFFE0 But this is unnescesary, as modern compilers will do this optimisation for you. However, if chosing a multiple to round down to, it still helps if you chose one that is a power of two so that the compiler can do these optimisations. AE. -- |
X-G
Member #856
December 2000
|
Or better yet (?)... x &= ~0x1f; (Does not assume 32-bit integer.) -- |
orz
Member #565
August 2000
|
Minor caveats: x = (x/32) * 32; is not equivalent to x = (x>>5)<<5; for cases were x is negative. The first rounds towards zero, the second rounds towards negative infinity. Quote: But this is unnescesary, as modern compilers will do this optimisation for you. However, if chosing a multiple to round down to, it still helps if you chose one that is a power of two so that the compiler can do these optimisations. Last I checked, if the variable was of an signed type, MSVC would branch on the sign, do the bitwise operations for positive numbers, and for negative numbers first negate, then do the bitwise stuff, then negate the result. All that just to get the correct rounding rules on negative numbers. |
Tobias Dammers
Member #2,604
August 2002
|
I'm wondering whether branching for something this simple is a good idea... if there is a random distribution of positive and negative numbers to be divided, this will kill branch prediction... wouldn't the integer divide be faster on modern hardware in that scenario? --- |
orz
Member #565
August 2000
|
Quote: I'm wondering whether branching for something this simple is a good idea... if there is a random distribution of positive and negative numbers to be divided, this will kill branch prediction... wouldn't the integer divide be faster on modern hardware in that scenario?
I haven't benchmarked the approaches, but my guess would be: |
Tobias Dammers
Member #2,604
August 2002
|
It depends on what you use it for. --- |
xinco1
Member #8,061
December 2006
|
Ok, and what is the best way of rounding up? |
GullRaDriel
Member #3,861
September 2003
|
If it is not a time critical function who need to round your number, then do not take care of any optimization and use x = (x/32) * 32; (as ML said). It will take care of positive/negative value and will avoid you from the (Does not assume 32-bit integer.) thing. Plus, a decent compiler will take care of those sort of optimization for you. Generally, I can tell that you first need to fully develop your application. _ "Code is like shit - it only smells if it is not yours" |
Tobias Dammers
Member #2,604
August 2002
|
Quote: Ok, and what is the best way of rounding up?
Exactly the same, but before rounding, you add precision-1 to the input. rounded = ((original + 31) / 32) * 32;
--- |
X-G
Member #856
December 2000
|
Also, Bob wrote this: http://bob.allegronetwork.com/prog/tricks.html -- |
xinco1
Member #8,061
December 2006
|
Ok,thats that problem sorted, but I got another: |
Kauhiz
Member #4,798
July 2004
|
Care to actually describe the problem? Also, what is the zero doing in the code? --- |
Tobias Dammers
Member #2,604
August 2002
|
If I understand correctly, you have a tile map that is displayed on screen at a given scroll position, and you want to transform screen coordinates (e.g. from the mouse) into tile coordinates, and possibly back. mouse_x_rel = mouse_x - scroll_x; And then you need to transform pixels into tile coordinates. Since a tile is (in your scenario) 20 pixels wide, you must divide the screen coordinates by 20: tile_x = mouse_x_rel / 20; Or, in a more general approach: tile_x = mouse_x_rel / tile_w; If your tile width happens to be a power-of-two, you can substitute: tile_x = mouse_x_rel & (tile_w - 1);
...which is a lot faster. The reverse can be found by simply solving the above equation for mouse_x:
This gives you the upper-left corner of the tile in question; if you want the center, add tile_w / 2 to it. --- EDIT --- --- |
xinco1
Member #8,061
December 2006
|
What i meant was if I had this:
Thats what I've got. It draws the marker correctly to the grid but it is slightly out. What happens is the mouse is sometimes in one square but the marker is drawn to the square to the left. My question is how can I correct this so that the marker is drawn at the correct place? |
Simon Parzer
Member #3,330
March 2003
|
In your code, what are x and y good for? |
xinco1
Member #8,061
December 2006
|
X and Y are the positions of where the grid is drawn |
ImLeftFooted
Member #3,935
October 2003
|
int makePow2(int x) { x--; x |= (x >> 1); x |= (x >> 2); x |= (x >> 4); x |= (x >> 8); x |= (x >> 16); x++; return x; } This is the code I'm using to upsize my textures to a power of 32. |
Bob
Free Market Evangelist
September 2000
|
Dustin said: This is the code I'm using to upsize my textures to a power of 32. And you can find an explanation for it here. -- |
ImLeftFooted
Member #3,935
October 2003
|
Quote: And you can find an explanation for it here [bob.allegronetwork.com]. Whenever you link to that page I always think how useful the thing is. But then when I actually need it I've forgotten it exists. |
|