math.round has problems or bug?

I not sure I understand your follow on question, but if you’re asking:

“Is it normal for square root calculations to return 0?”

The answer is, “Yes, if the value you are taking the square root is VERY small or zero.”

Also, it is better not to do anything that might result in a divide by zero.  So, in this case doing that calculation in the call to sqrt() is a bad idea as it may result in a return value of 0.

I did not explain well.

My question is:

Why if I do(using the same data):

local dx, dy = x-var1, y-var2 dx, dy = round(dx), round(dy) print(dx)

when “x-var1” is equal to “0”, “dx” takes “0”

while if I do

local dx, dy = round(x-var1), round(y-var2) print(dx)

when “x-var1” is equal to “0”, “dx” takes “-1.#IND

it seems that passing as a parameter to “math.round()” operations does not work as well as passing finite values

p.s. (Try the tests attached in the above code (first post) to confirm)

You’re problem is not the rounding but, as roaming already told, your division by 0 which is kind of not defined but the result is ccgm become infinite which, as a result changes the results from your foo function and then var1 which is used in the next iteration of foo.

 

You can verify this f.i. by adding the following lines after your local ccgm = … line of code

 

[lua]

if ((dx^2) + (dy^2)) < 0.00000000000000000001 then

    ccgm = 0.00000000000000000001

end

[/lua]

  1. yes.  2.  that’s not the issue

your two functions are not numerically equivalent, so i won’t bother running the test:  the first rounds AFTER the sqrt-division, the second rounds BEFORE the sqrt-division.  so no surprise the results differ.  your question is equivalent to asking:

dx = 1e-12 ccgm = 1 / dx -- no problem, ccgm now == 1e12 dx = math.round(dx) -- versus dx = math.round(1e-12) -- dx now equals zero ccgm = 1 / dx -- division by zero, ccgm now undefined (+infinity per ieee754, ie ccgm == math.huge)

you’re on the fringe of precision here, try printing all 15 digits of your sqrt result just prior to division to see the difference.

@dave

You’re wrong here as the rounding, within the scope of the function, is actually done on the same and unchanged variable/value (dx and dy) in both cases. You can just move the print/rounding code above the sqrt and still get the same problem.

The core is of course the division by 0 but only because it is feed back somehow into later iterations of foo.

i can accept that, as i didn’t run the code, still same problem only later

Ok grazie ragazzi!

Ho seguito tutti e ho capito.

Il problema era con le iterazioni successive non con la funzione “math.round”.

@davebollinger 

no later does not occur, because the rounding is always after to the square root

 
 
I agree w/ everything Michael said, except I want to give you one word of caution.  The value: 0.00000000000000000001 may be too small for some CPUs in some devices.  It will round to 0 or some weird value (not sure on this).
 
My suggestion is a modified version of Michael’s solution.
 

-- Set this in main.lua before executing any of your game code math.tiny = math.tiny or 1e-6 -- safer in case math.tiny ever becomes part of lib -- Now you can use it anywhere if ((dx^2) + (dy^2)) \<= math.tiny then ccgm = math.tiny end

FYI, there is already a math.huge as part of the math.* library

PS - My choice for math.tiny isn’t really that tiny, but it is definitely small enough for any game calculation I can think of.

@maximo,

I think everyone here will agree, this has nothing to do with math.round()nor inline calculations.

The problem is a division by zero which you are not checking for.

Once more, the problem is this line,

local ccgm = staticVal / sqrt(dx^2 + dy^2)

specifically, this calculation,

sqrt(dx^2 + dy^2)

which produces the zero in the division-by-zero.

Absolutely, I didn’t meant this to be a solution but just a quick way to show where the actual error came from without thinking the actual reason behind the code.

You’d also probably do the tiny check before squaring the values as tiny^2 will be even smaller and then set ccgm to actually a very big value as whatever divided by a tiny value results in a very big one. But maximo is the one who knows best what the code is intended to do and how to adjust it.

@roaminggamer

Yes, the basic problem is that because if I divide by 0 then call the function foo dx already has an invalid value.

For how I had written the code I took a while to understand it but thanks to you I have to go

I do this…

local newValue = 1 / mclamp(myValueThatMayBeZero, 0.00000000000001, myValueThatMayBeZero)

@sgs

That would not work with negative values.

If you know you only need/want positives, using max instead of clamp would be the better solution as clamp will do an upper bounds check never required.