3 doesn't equal 3?

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
MrGreen
Prole
Posts: 12
Joined: Thu Aug 01, 2019 2:07 pm

3 doesn't equal 3?

Post by MrGreen » Thu Aug 01, 2019 2:42 pm

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

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

Re: 3 doesn't equal 3?

Post by raidho36 » Thu Aug 01, 2019 6:00 pm

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?

Post by MrGreen » Thu Aug 01, 2019 6:39 pm

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

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

Re: 3 doesn't equal 3?

Post by pgimeno » Thu Aug 01, 2019 6:42 pm

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?

Post by MrGreen » Thu Aug 01, 2019 7:05 pm

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.

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

Re: 3 doesn't equal 3?

Post by pgimeno » Thu Aug 01, 2019 10:07 pm

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?

Post by MrGreen » Thu Aug 01, 2019 11:23 pm

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

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

Re: 3 doesn't equal 3?

Post by YoungNeer » Fri Aug 02, 2019 8:55 am

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 :rofl:

Regards
My Github- your contribution is highly appreciated

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

Re: 3 doesn't equal 3?

Post by zorg » 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
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 :3True 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?

Post by MrGreen » Fri Aug 02, 2019 10:13 am

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 :rofl:
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
(8.61 KiB) Downloaded 69 times
Gitter.png
Gitter.png (5.27 KiB) Viewed 2797 times
conf.lua
(52 Bytes) Downloaded 65 times

Post Reply

Who is online

Users browsing this forum: No registered users and 27 guests