## 3 doesn't equal 3?

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
MrGreen
Prole
Posts: 12
Joined: Thu Aug 01, 2019 2:07 pm

### 3 doesn't equal 3?

Hello, I am new to LÖVE and I want to start with a very basic snake game. But as soon as I started, I got a problem.

What I am trying to do with this is, that when I am going in one direction, I cannot be able to move in the opposite direction. So I created an equation for it: (4/3)*(x^3) - 10*(x^2)+ (65/3)*x - 10

Code: Select all

control = {"up", 1, "right", 2, "down", 3, "left", 4}
x =(4/3)*((control[1 + 1])^3)-10*((control[1 + 1])^2)+(65/3)*(control[1 + 1])-10
print(x) <---- 3 gets printed
if x == 3 then
print("dumm") <---- "dumm" is not printed, WHY????
end

Although the equation returns 3, "dumm" is not printed.

What am I doing wrong?

This is my actual code, but the code above shows my problem more clearly, I think.

Code: Select all

if love.keyboard.isDown(control[1]) and direction ~= x and direction ~= control[1 + 1] then
--	if grid[frontX][frontY] + 1 ~= grid[frontX][frontY - 1] and verti ~= -1 then
direction = control[1 + 1]

--	end
end

raidho36
Party member
Posts: 2063
Joined: Mon Jun 17, 2013 12:00 pm

### Re: 3 doesn't equal 3?

Floating point numbers don't store values exactly, only approximately. Lua uses 64 bit floats so you get approximation with precision to about 15 digits. There could be about 300 zeroes on either side but only 15 decimal places to hold the actual number.

Double precision floats have a special property: they can store integers exactly. So you get 53 bits of integer storage to play around, but the numbers must be exact integers - every operation is limited by the precision and this tiny error accumulates and amplifies, so arriving back at an "integer" through some math won't work, because it won't be an exact integer.

If your number is only slightly off, you can use rounding at the end of your operation. Alternatively, you can check if the final number is within certain range, rather than exactly equal to a specific number.

MrGreen
Prole
Posts: 12
Joined: Thu Aug 01, 2019 2:07 pm

### Re: 3 doesn't equal 3?

Okay thank you for your answer. I will try to round it then.

pgimeno
Party member
Posts: 2313
Joined: Sun Oct 18, 2015 2:58 pm

### Re: 3 doesn't equal 3?

MrGreen wrote:
Thu Aug 01, 2019 2:42 pm

Code: Select all

print(x) <---- 3 gets printed
if x == 3 then
print("dumm") <---- "dumm" is not printed, WHY????
end

What raidho said. Lua by default does not print numbers with enough decimal digits as to distinguish them. Try this instead:

Code: Select all

print(string.format("%.17g", x))

An improvement on your formula would be to defer the division to the very end:

Code: Select all

x =(4*control[1 + 1]^3-30*control[1 + 1]^2+65*control[1 + 1]-30) / 3

Note I've multiplied by 3 all terms.

If the numerator in parentheses is a multiple of 3, the division will be exact. Your intermediate results like 4/3 and 65/3 are not exact and may introduce rounding errors.

MrGreen
Prole
Posts: 12
Joined: Thu Aug 01, 2019 2:07 pm

### Re: 3 doesn't equal 3?

pgimeno wrote:
Thu Aug 01, 2019 6:42 pm

Code: Select all

x =(4*control[1 + 1]^3-30*control[1 + 1]^2+65*control[1 + 1]-30) / 3

Oh, that is even better.

Rounding worked, too:

Code: Select all

math.floor(4/3*(control[1 + 1])^3-10*(control[1 + 1])^2+65/3*(control[1 + 1])-10)
But I like your idea better. Thank you.

pgimeno
Party member
Posts: 2313
Joined: Sun Oct 18, 2015 2:58 pm

### Re: 3 doesn't equal 3?

Good to know you have it working. Just a note in case you find yourself in similar situations in the future and decide to go the rounding way:
MrGreen wrote:
Thu Aug 01, 2019 7:05 pm
Rounding worked, too:

Code: Select all

math.floor(4/3*(control[1 + 1])^3-10*(control[1 + 1])^2+65/3*(control[1 + 1])-10)
That's rounding towards negative infinity, i.e. floor. That only works if your numbers are consistently equal or higher than the target number, but depending on how the intermediate operations are rounded, it may be the opposite case, i.e. instead of 3.000000x you could have gotten 2.999999x, and the floor of that is 2.0 instead of 3.0.

To solve that, you can use "Round to nearest" which can be implemented by adding 0.5:

Code: Select all

local function round(x)
return math.floor(x + 0.5)
end

With this rounding method, ties are always rounded towards positive infinity, e.g. round(2.5) is 3 and round(-2.5) is -2.

MrGreen
Prole
Posts: 12
Joined: Thu Aug 01, 2019 2:07 pm

### Re: 3 doesn't equal 3?

Okay, I think this will be very helpful in the future. Thank you for your help and tips.

YoungNeer
Party member
Posts: 118
Joined: Wed May 15, 2019 7:49 am

### Re: 3 doesn't equal 3?

MrGreen wrote:
Thu Aug 01, 2019 2:42 pm
What I am trying to do with this is, that when I am going in one direction, I cannot be able to move in the opposite direction. So I created an equation for it: (4/3)*(x^3) - 10*(x^2)+ (65/3)*x - 10
Honestly saying you don't even need that equation on first place! Creating is snake game is much more simpler than that. i don't know why are you making it any more complicated than it already is - but here is an *awesome* snake game that you can refer to. You shouldn't find anything more complicated than the aabb collision

Regards
My Github- your contribution is highly appreciated

zorg
Party member
Posts: 2995
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

### Re: 3 doesn't equal 3?

True, you could just do something like the following:

Code: Select all

-- assuming you store the movement direction as dx,dy in a table, like direction = {0,0} initially
love.keypressed = function(k,s)
if s == 'up' then
direction[1] = love.keyboard.isScancodeDown('down') and direction[1] or 1.0
direction[2] = 0.0 -- orthogonal movement
elseif s == 'down' then
direction[1] = love.keyboard.isScancodeDown('up') and direction[1] or -1.0
direction[2] = 0.0 -- orthogonal movement
elseif s == 'left' then
direction[1] = 0.0 -- orthogonal movement
direction[2] = love.keyboard.isScancodeDown('right') and direction[2] or -1.0
elseif s == 'right' then
direction[1] = 0.0 -- orthogonal movement
direction[2] = love.keyboard.isScancodeDown('left') and direction[2] or 1.0
end
end

This code should guarantee that the opposite directions on both axes will not turn the snake around, without having bias for any of the keys, and it's easier to do the movement based on normalized vectors like the direction variable (and it forces movement only vertically and horizontally, not diagonally)
Usually the keyreleased callback would also be used, but for snake, it's not necessary, since the snake will still continue moving even if you release the last key input.
Also, i used scancodes instead of keyconstants, because it's better if you want to consider people who don't use qwerty keyboards. (not really relevant this time though, with just the cursor keys)
Me and my stuff True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.

MrGreen
Prole
Posts: 12
Joined: Thu Aug 01, 2019 2:07 pm

### Re: 3 doesn't equal 3?

YoungNeer wrote:
Fri Aug 02, 2019 8:55 am
Honestly saying you don't even need that equation on first place! Creating is snake game is much more simpler than that. i don't know why are you making it any more complicated than it already is - but here is an *awesome* snake game that you can refer to. You shouldn't find anything more complicated than the aabb collision
To be honset I was not able to get this going. I saw some issues which I wanted to try out, but I think the version is too old. I do not have a good knowledge in programming and that is why I make it so complicated.
zorg wrote:
Fri Aug 02, 2019 9:32 am
True, you could just do something like the following:

Code: Select all

-- assuming you store the movement direction as dx,dy in a table, like direction = {0,0} initially
love.keypressed = function(k,s)
if s == 'up' then
direction[1] = love.keyboard.isScancodeDown('down') and direction[1] or 1.0
direction[2] = 0.0 -- orthogonal movement
elseif s == 'down' then
direction[1] = love.keyboard.isScancodeDown('up') and direction[1] or -1.0
direction[2] = 0.0 -- orthogonal movement
elseif s == 'left' then
direction[1] = 0.0 -- orthogonal movement
direction[2] = love.keyboard.isScancodeDown('right') and direction[2] or -1.0
elseif s == 'right' then
direction[1] = 0.0 -- orthogonal movement
direction[2] = love.keyboard.isScancodeDown('left') and direction[2] or 1.0
end
end

I was not able to understand what it is really doing; If you could explain me that again for an idiot like me, that would be awesome.

Thank you for your replies and for trying to help me. I attached my files, even if they are very chaotic.
main.lua