Cart #sufehasede-0 | 2019-10-25 | Code ▽ | 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 ▽ | 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 ▽ | 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)`

 `tostr(.5/10000,true)`

will return 0x0000.0003.

Cart #shox_dw_decimal-0 | 2019-10-26 | Code ▽ | 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 ▽ | 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)