Log In  

Cart #sufehasede-0 | 2019-10-25 | Code ▽ | Embed ▽ | No License

I was interested in making a type of high-number integer counter relying on the length and accuracy of 4-digit decimal numbers less than 1 when I came across this little slice of misfortune.

Here is the source to see there is no complication on my part:

-- real numbers are flawed!

function key()
  repeat
    flip()
  until btnp(4)
end

b=1
e=10

for i=1,5 do
  cls()
  ?"counting "..b.." to "..e.."."
  key()
  ?""
  for i=b,e,b do
    ?i
  end
  key()
  b/=10
  e/=10
end
?""
color(10)
?"complete!"
repeat
  key()
until forever

Any solutions on how to get the correct numbers here ? And ... does this error extend to LUA or just Pico-8 ?

P#69284 2019-10-25 23:39 ( Edited 2019-10-26 18:27)

It extends to all computer representations of floating-point numbers. That cart demonstrates a Floating-Point error. It's not PICO-8's fault. It's not Lua's fault. It's a very common bug in programming, and it's not really preventable afaik.

Here's a section of the Wikipedia article for Floating-point arithmetic.

And here's the same error demonstrated in my browser:

P#69287 2019-10-25 23:56
:: dw817

It makes no sense though, @TheV360.

I mean AFAIK decimal numbers just added or subtracted should not be retrieving a wrong value. I wrote code earlier to show you could add and subtract any number of digits, well past trillions:

https://www.lexaloffle.com/bbs/?tid=35715

Granted I had planned to use multiply and divide for these real numbers in my current experiment, but surely it can ... merely add and subtract by .1, .01, .001, and .0001 ?

And I know this error did not occur on the TRS-80 or Apple ][ computer. Because I used floating point numbers then.

Is this some type of encroaching error that has been carried through future OS and never resolved ?

Alright, let's focus for a second then.

Is there a perfect solution or common kludge used today to get past this ?

Now I was trying THIS, and it works, but I don't know how FAR it works, nor is it a good solution as it expects a truncation based on the value itself, which could mess up during complex calculations:

Cart #kowujitame-0 | 2019-10-26 | Code ▽ | Embed ▽ | No License

-- real numbers are flawed!

function key()
  repeat
    flip()
  until btnp(4)
end

b=1
e=10

for i=1,5 do
  cls()
  ?"counting 0 to "..e.."."
  key()
  ?""
  for j=0,e,b do
    n=j
    n=n+(b/2)
    n=sub(n,1,i+1)
    ?n
  end
  key()
  b/=10
  e/=10
end
?""
color(10)
?"complete!"
repeat
  key()
until forever
P#69288 2019-10-26 00:15 ( Edited 2019-10-26 00:16)
1

Floating point math is.... iffy. See this great video for a good explanation:

P#69290 2019-10-26 01:49
:: dw817

SOLUTION !

Yessiree ! I definitely found a way to fix it.

First off, try this, cause this is weird.

a=0
a=a+.5/10000
?a

You get zero as you would expect cause it's smaller than .0001 which is the limitation on variables.

But now try this in immediate mode with the code above:

b=0
if a!=b then print"error" end

THEY DO NOT MATCH !

So surely one of them is a string, right ? I mean you only have a few variable types, string, table, or number. There is nothing further, right ?

Let's check:

?type(a)
?type(b)

No, they're both numbers. But ... somehow different. Despite both containing only zero. So ... what's going on here ?

Wow, I wish I knew. :D

But, we can use this to repair our numbers, and we don't need an index to keep track of now. Here is the first code above with solution:

Cart #punabiyepo-0 | 2019-10-26 | Code ▽ | Embed ▽ | No License

Here is the final code:

-- real numbers are repaired!
-- by dw817

function key()
  repeat
    flip()
  until btnp(4)
end

b=1
e=10

for i=1,5 do
  cls()
  ?"counting 0 to "..e.."."
  key()
  ?""
  for j=0,e,b do
    n=j+.5/10000
    ?n
  end
  key()
  b/=10
  e/=10
end
?""
color(10)
?"complete!"
repeat
  key()
until forever

So ... is that all it is ? That single line where you add .5/10000 and ... despite that calculated value by itself clearly being zero it somehow fixes it ? Yep. And that's fine, I'll use that method if that's what it takes to get "accurate" values.

Truth is often stranger than fiction. I think that is happening here.

Now, would someone like to explain WHY this works ? :)

P#69289 2019-10-26 02:00 ( Edited 2019-10-26 02:01)
:: dw817

Watching your video, @MBoffin, quite interesting ! I need to know this stuff ...

P#69291 2019-10-26 02:06
:: dw817

Eye (O)(-) opening ! I recommend anyone having problems with floating point to watch the video.

The most important thing stated is (1/3) x3, which we understand as humans being the value of 1 is NOT the same as 0.333333333 x3 to a computer which is 0.999999999.

SO ! Therein lies the problem. And, no, I can't see an easy solution around it.

Perhaps future fantasy consoles or even computers for that matter might have something called the "human" factor, optional in math, which looks at a calculation and tries its level best to calculate the way a human would - and more importantly, to return a HUMAN value that makes sense. In this case,

a=1/3
b=a*3
?b

Would in fact return the value of 1.

. . .

Still doesn't explain why there can be two variables both with zero and yet ... according to a comparison, they somehow do not match.

P#69292 2019-10-26 02:23 ( Edited 2019-10-26 03:30)
2

To put it simply, print is lying to you. Numbers in pico-8 are 16:16 fixed point numbers(according to the manual). So technically they are not floating point numbers, though the video is still helpful as for how values less than 1 or represented. The 16:16 means that each side of the decimal point is represented by 16 bits or 2 bytes. To see the hexadecimal value of a number use:

tostr(num,true)

For .0001 this returns 0x0000.0006. This tells us that we can go a bit smaller. However, using

tostr(0x.0001) 

will return 0. This value still exists though.

tostr(0x.0001,true)

will return 0x0000.0001. And, if we follow your example

tostr(.5/10000,true)

will return 0x0000.0003.

Here is your demonstration with hexadecimal values added.

Cart #shox_dw_decimal-0 | 2019-10-26 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
2

P#69325 2019-10-26 17:20
:: dw817

Zero zero zero three !

The cake is a lie ! But I LOVE cake. Well, actually like. Pie if it's done right is much better.

Still, PRINT being deceptive ? I would not have expected this. Question. Is it possible to squeeze out a 5th decimal place now since apparently it does indeed exist and PRINT is merely not displaying it ?

Hmm ... this changes so much and explains why zero did not equal zero earlier.

Thanks, @Shoxidizer !

P#69328 2019-10-26 17:32 ( Edited 2019-10-26 19:54)
2

You won't be able to get a whole extra tenths place, there are not enough values smaller than .0001.

The attached program displays how a given value is display, it displayed as a fractional form, the value that its displayed value generates, and how that is displayed.

Cart #shox_number_explorer-0 | 2019-10-27 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
2

By the way, you ever try these in the console?

print(.0001)
print(.0002)
print(.0003)

One of these is not like the others.

P#69348 2019-10-27 02:59 ( Edited 2019-10-27 03:31)
:: dw817

Definitely, @Shoxidizer. .0001 is coming out zero. Makes me wonder how all those great 3D programs execute as well as they do without running into errors.

And your Hexadecimal program above ? Newest gadget to explore. Saved to my folder of favorite offline games. Very interesting to play with. :D

Decimal of string of decimal is especially an area I want to experiment with.

P#69350 2019-10-27 03:42 ( Edited 2019-10-27 04:08)

[Please log in to post a comment]

Follow Lexaloffle:        
Generated 2020-10-23 11:34 | 0.078s | 4194k | Q:97