Log In  

Hi everyone, I think this can't be a bug that only I just found out so I'm posting it here for some help instead of in the bugs forum.

I seem to be having the weirdest behaviour easing out a negative var towards 0: it never becomes zero again (either negative or positive), despite printing as such. Check the below reproducer code and gif, neither y==0 nor y==-0 conditions catch the zero, even though at first you can see true.

Please help?

Thanks!

function _init()
 y=0
end

function _update()
 y*=0.85
 if btn(2) then
  y-=0.65
 end
end

function _draw()
 cls()
 print("time: "..time())
 print("y="..y)
 print("is y==0? "..(y==0 and 'true' or 'false'))
 print("is y==-0? "..(y==-0 and 'true' or 'false'))
end
P#113348 2022-06-19 11:45

2

Stuck in a line using tostr() to get the raw hexadecimal:

 print("y="..tostr(y,1))

...and it looks like the way PICO-8's rounding works, 0.85 times 0xFFFF.FFFA (negative 0x0.0006) still equals 0xFFFF.FFFA, so it never gets any closer than that to 0.

I think it might be worth to stick in some close-enough check if you need the delta to reach zero.

P#113350 2022-06-19 12:38
1

Alternatively, if you want a very silly solution: it does converge from positive, so spending six tokens like:

 y=0.85*abs(y)*sgn(y)--sgn(y) must be the last part!

makes the math round towards 0 both ways and reach 0.

P#113362 2022-06-19 14:00 ( Edited 2022-06-19 14:00)

Weird rounding issues, got it - makes sense now. But that "silly" solution of yours is brilliant, I just can't wrap my head around how that works?! Shouldn't abs(y)*sgn(y) be the same as y? (more rounding voodoo happening I suppose?)

P#113371 2022-06-19 15:41
1

Also, after your kind explanation I went with the following close enough solution (I'm sure there's an obvious way to optimise what I have below, my pico-8 kung-fu is not good enough):

y*=0.85
if y>-0.1 and y<0.1 then
   y=0
end
P#113372 2022-06-19 15:59
1

So, I think what happens is that PICO-8 rounds arithmetic down - i.e. towards negative infinity - which means for very small numbers, 0.85 times a positive y will round down and towards zero, but 0.85 times a negative y will round down and away from zero ... so by flipping the sign on negative numbers before doing arithmetic and again after, down will always be towards zero.

But I do think setting "this small number equals zero" is a better way to do it.

P#113377 2022-06-19 17:51
1

Ah got it, makes sense thanks!! Well I suppose your suggestion is the proper workaround when precision is required, whereas mine is just a shortcut for when rough is good enough. Thank you very much for everything!

P#113379 2022-06-19 18:09
1

Usually with decimal numbers like this, it can be difficult to determine the exact representation in binary, so what I usually do is implement a function to check if it is in a very small range:

function near(x,y,p)
 p=p or 0.1 
 return x>=(y-p) and x<(y+p)
end

-- demo
for i=-1,1,0.09 do
 print(tostr(i).." "..tostr(near(i,0)))
end
P#113399 2022-06-20 07:42 ( Edited 2022-06-20 07:42)

Alternatively you could check against the hexidecimal value, rather than the decimal digit.

In your print statements, rather than check for y == -0 check instead for y == 0xffff.fffa.

If you set a variable, say "z", to -0 then check its hex value, it will be 0x0000.0000 the same as setting to 0. Probably P8 is giving you a sane version of 0, even though you asked for otherwise.

But your countdown is dealing in the raw values, so you can check against the raw values via hexadecimal equivalence.

P#113420 2022-06-20 22:50
1

> Usually with decimal numbers like this, it can be difficult to determine the
> exact representation in binary, so what I usually do is implement a function
> to check if it is in a very small range:

Thanks @MrGoober, that's a slightly saner approach actually.

@ChristopherD in this case I really want the approximate check, i.e., catching a bunch of near enough values, not an exact one - and P8 was forcing me to deal with a precise value.

P#113439 2022-06-21 10:49
1

Hi @matamouros:

Don't forget that SGN(0) = 1 in Pico-8 which is very non-standard with most BASIC programming languages as it is normally zero. That could also be giving you trouble.

You can fix it with a function:

function mysgn(a)
  if (a==0) return 0
  return sgn(a)
end
P#113457 2022-06-21 23:47 ( Edited 2022-06-21 23:48)

[Please log in to post a comment]

Follow Lexaloffle:          
Generated 2022-12-05 03:24:32 | 0.028s | Q:23