For double f, float g, How to find the largest int i such that I * g <= f

UPDATE : Thanks, Kevin, I meant <= in the title, not <.

It is right? This is the best I managed after a difficult time on the problem:

 public int candidate_answer(double f, float g) { int test = (int)Math.floor(f / g); if ((test + 1) * g <= f) { test++; } return test; } 

Background:

The application is a simple game that I took upon myself for a previous programmer. Curiously, he decided to mix floats and double it pointless, both in member variables and in variables, so there are many unnecessary implicit and explicit castings going up and down.

The playerโ€™s coordinates are double x, y (it is believed that the player is a point). There is a floating TILE_SIZE, and in the world there are a certain number of rows and columns, a number of tiles, as well as some general processing outside the borders. Assuming the coordinate (x, y) is within the borders, I'm trying to figure out which element the user is in, based on x (to get a column) or y (to get a row). This is similar to programmer 101.

WLOG; At first I just did col = (int)(x/TILE_SIZE) . But, as I found, for example, .5 / .1f <5, and therefore (int)(.5/.1f) == 4 , the wrong answer. This led to the above statement and statement of the problem.

Then I found that, for example, (int)(-9.999999747378752E-5 / .1f) == 0 , which led me to call Math.floor first.

But now I'm not sure what other errors are hidden in this approach or what a better approach would be.

(This may not seem like such a big problem if the user is right on the threshold of being on one line or another, and we accidentally rounded up to the wrong one, but the real problem is in the code, where we see unexpected changes in the sign (+, -, 0 ). For example, some of the code suggests that if the user is on the tile at the point (r, c), then it actually contains this tile geometry. When this is not the case, we get things like negative distances, when only non-negative ones are expected, etc. and this causes threats to trelby and while loop break, etc.)

+6
source share
3 answers

I think you should try to fix the root problem (.1f is too far from .1), i.e. turn TILE_SIZE into double or use floats sequentially throughout. Otherwise, you may encounter similar problems caused by minimal rounding errors throughout the code. The candid_answer function is to crack a problem that should not exist in the first place.

PS

For this specific task, you can simply find a formula that is more reliable, that is, not sensitive to minimal rounding errors in only one direction. Try to place the player in the center of his field, and not on the edge of the tile, where he can easily get into rounding errors:

 col = (int)((x + MINIMAL_STEP_SIZE / 2.0) / TILE_SIZE) 

(Ideally, the MINIMAL_STEP_SIZE / 2 part will already be part x instead of adding here)

+3
source

Using the double path is the way. However, this does not solve the root problem: the use of floating-point arithmetic is always associated with rounding errors.

When using floating point arithmetic, it is always useful to work with Epsilon (e) precision:

If you want to check if x is equal to y (where one variable is a floating-point type), use the following pattern:

 if(xy < e){ ... } 

Epsilon should be defined (globally or in your opinion for a specific domain) based on your requirements. For instance:

 e = 0.00001d; 
+1
source

If f and g are positive (they seem), your method can be reduced to one simple calculation:

 public static int candidate_answer(double f, float g) { return (int)(g/f); } 

This is correct because if

 i*f <= g 

then, dividing both sides by f , we get

 i <= g/f 

Casting to int automatically gives you "the largest int value, less than or equal to the result", because when you discard all non-integer parts, it is discarded - this is like making a floor () call.


If f or g allowed to be negative, this approach will still work, but you need to deal with the icon (not a lot of code, but I doubt it is necessary, given that the question is formulated.

0
source

Source: https://habr.com/ru/post/948897/


All Articles