Home
JAQForum Ver 20.06
Log In or Join  
Active Topics
Local Time 13:58 02 May 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : [MicroMite]Strange Behaviour with 9999999

Author Message
G8JCF

Guru

Joined: 15/05/2014
Location: United Kingdom
Posts: 676
Posted: 02:09pm 24 Jul 2014
Copy link to clipboard 
Print this post

Hi

I think I've come across an anomaly with the way 9999999 is treated/processed by MMBasic on the Micromite.

Please try this on a uMite.


List all

For A=9999995 To 10000005
Print Str$(A\1E6)+Str$(A-(A\1e6)*1E6,6,0,"0")
Next
> RUN
9999995
9999996
9999997
9999998
10-00001
10000000
10000001
10000002
10000003
10000004
10000005
>


The numbers printout as expected except for 9999999 !

Can anyone advise me what's going on please ? (as a workaround if I get a result of "10-00001" I just replace it with 9999999, but that just doesn't seem right !)

Thanks in advance

Peter
The only Konstant is Change
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 5909
Posted: 05:23pm 24 Jul 2014
Copy link to clipboard 
Print this post

It is doing the calculations more or less correctly.
A is outside the precision of 32bit FP so odd things can happen.

For A=9999995 To 10000005
'Print Str$(A\1E6)+Str$(A-(A\1e6)*1E6,6,0,"0")
print Str$(A-(A\1e6)*1E6)
Next


I can't think of an easy solution...

Jim
VK7JH
MMedit   MMBasic Help
 
Geoffg

Guru

Joined: 06/06/2011
Location: Australia
Posts: 3165
Posted: 12:09am 25 Jul 2014
Copy link to clipboard 
Print this post

That seems to be a bug in the formatting routines used by PRINT.

I have put it on my todo list for when I get back (late August).

Geoff
Geoff Graham - http://geoffg.net
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 3660
Posted: 01:51am 25 Jul 2014
Copy link to clipboard 
Print this post

A bit of a weird bug but good it's been found!

(Doesn't look to be outside the precision.)

John
 
G8JCF

Guru

Joined: 15/05/2014
Location: United Kingdom
Posts: 676
Posted: 03:35am 25 Jul 2014
Copy link to clipboard 
Print this post

Thanks Geoff,

Hope you are having a restful and enjoyable time travelling

Peter
The only Konstant is Change
 
Geoffg

Guru

Joined: 06/06/2011
Location: Australia
Posts: 3165
Posted: 08:22pm 28 Aug 2014
Copy link to clipboard 
Print this post

I have finally got down to investigating this "bug" and I must report that it is not a bug but a limitation of the precision that you can get with single precision floating point calculations.

The critical part is this expression:
A-(A\1e6)*1E6


Here you divide a number by a million then multiply the result of that calculation by a million and you don't end up with the same number!

I have yet to look at introducing integer variables but if I can get them to work it would give you the perfect solution.

Geoff


Geoff Graham - http://geoffg.net
 
G8JCF

Guru

Joined: 15/05/2014
Location: United Kingdom
Posts: 676
Posted: 04:57am 29 Aug 2014
Copy link to clipboard 
Print this post

Hi Geoff

You must be back down-under ! Hope you had a really wonderful time on the Emerald Isle and I hope you got to tour Co. Kerry in particular.

So does this mean that (9,999,999 / 1E6 * 1E6) will always give the "incorrect" answer, whereas (9,999,998 / 1E6 * 1E6) and (10,000,000 / 1E6 * 1E6) will always give the "correct" answer, ie why is 9,999,999 so special ? I can see it's a boundary condition, but it does seem peculiar that this number uniquely out of 10's of millions of its peers is the one which doesn't seem to behave as all the others do.

There clearly must be a rational and logical reason, but the uniqueness of the the peculiarity and the fact that it's all 9's (at least it's not all 6's !!), and that there is a '-' sign in the number piqued my interest. As I said in practice I just work around it by catching the condition and substituting 9 999 999 back in whenever I see 10-00001.

Take care and as always, thank you for developing the 'Mites and MMBasic

Peter
The only Konstant is Change
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 3660
Posted: 06:28am 29 Aug 2014
Copy link to clipboard 
Print this post

To understand it better I suggest looking up (or figuring out) how the fp numbers are stored. The 32-bits will be split something like n bits for the exponent, y bits for the mantissa and I think 1 bit for the sign.

Then dump out the various numbers as bits, split up into their parts.

Do it for each of the calculations in turn, and look how the bits change.

They'll be almost alike and I reckon you'll see what's happening.

I think you'll find it's akin to using base 10 (everyday arithmetic) where things like
10 / 3 * 3 does not get back to 10 with fixed-length (fixed precision) arithmetic. Similarly, 1000000 / 3 * 3 doesn't go back to 1000000, and so on.

(Assuming it's not a bug.)

JohnEdited by JohnS 2014-08-30
 
twofingers
Guru

Joined: 02/06/2014
Location: Germany
Posts: 1133
Posted: 07:25am 29 Aug 2014
Copy link to clipboard 
Print this post

  Quote  To understand it better I suggest looking up (or figuring out) how the fp numbers are stored.

Hint: we can do this easy with the peek function (MMBasic 4.5, Maximite).

But I get on a Duinomite using this code:
For A=9999995 To 10000002

Print Str$(A\1E6)+Str$(A-(A\1e6)*1E6,6,0,"0")

For offset = 0 To 3
Print Right$("0000000"+Bin$(Peek(VAR A, offset)),8)
Next offset
Print
Next A

this results:
999995
01111011
10010110
00011000
01001011

999996
01111100
10010110
00011000
01001011

999997
01111101
10010110
00011000
01001011

999998
01111110
10010110
00011000
01001011

10-1
01111111
10010110
00011000
01001011

100
10000000
10010110
00011000
01001011

101
10000001
10010110
00011000
01001011

102
10000010
10010110
00011000
01001011


MichaelEdited by twofingers 2014-08-30
 
Geoffg

Guru

Joined: 06/06/2011
Location: Australia
Posts: 3165
Posted: 01:24pm 29 Aug 2014
Copy link to clipboard 
Print this post

Peter,

Yes, back thanks. I missed out on Co. Kerry - next time perhaps.

The strange result is because floating point stores large numbers as an approximation and you are attempting to recover a precise number. In your example the "glitch" occurred at 9999999 but if you scanned a large set of numbers you would see other "glitches" where the approximation did not match the reality. The larger the numbers the more often you would see the effect.

Geoff
Geoff Graham - http://geoffg.net
 
twofingers
Guru

Joined: 02/06/2014
Location: Germany
Posts: 1133
Posted: 05:17am 30 Aug 2014
Copy link to clipboard 
Print this post

Where the glitches starts ...

  Quote  if you scanned a large set of numbers you would see other "glitches"


To deperminate the first glitch point I used this code (MMBasic 4.5, Duinomite)

Dim b(4)

SetTick 1000,progress

' Set a=1 or a=8388607, if you are in a hurry
For A=1 To 10000002
x=Val(Format$(a,"%10.0f"))
'Print a, x, Format$(a,"%10.0f")
If a<>x Then Exit For
Next A

Print a, x, Format$(a,"%10.0f")
End

Sub progress
Print @(0,0)a, Format$(a,"%10.0f")
End Sub


First glitch point occurs at 8,388,610 for whole positive numbers.
8,388,610 is as binary floating point representation
00000001
00000000
00000000
01001011


Is 8,388,610 somehow a "special" number (it's very near 16,777,100/2 = 8,388,550)? Or shows this only the limits of the FORMAT$() or Val() function?

edit: Perhaps the point is somewhat earlier: 2^23 = 8388608.

This shows the problem better:

Dim b(4)

SetTick 1000,progress

For A=8388607 To 8388611'10000002
x=Val( Format$(a,"%15.0f"))
Print a, x, Format$(a,"%10.0f")
For i = 0 To 3
Print Right$("0000000"+Bin$(Peek(VAR a, i)),8)
Next i

Next A

End


Sub progress
Print @(0,0)a,Format$(a,"%10.0f")
End Sub


Display:
8.38861e+06 8.38861e+06 8388607
11111110
11111111
11111111
01001010
8.38861e+06 8.38861e+06 8388608
00000000
00000000
00000000
01001011
8.38861e+06 8.38861e+06 8388610
00000001
00000000
00000000
01001011
8.38861e+06 8.38861e+06 8388610
00000010
00000000
00000000
01001011
8.38861e+06 8.38861e+06 8388612
00000011
00000000
00000000
01001011


Seems there is a glitch hole at 8388608 (2^23)!

May be µMites are different.


2. edit: Some useful formulas for converting a
floating point number to binary (IEEE 754) and back.
(MMBasic 4.5, Duinomite/Maximite)
Bias=127
x= -73,23 ' (almost) any floating point number

vz=x<0 ' sign
x=Abs(x)
e=log2(x) ' exponent
EB=e+Bias
m=(x/2^e-1)*2^23 ' mantissa

fp=(-1)^vz*(1+m/2^23)*2^(EB-Bias)

Print -1^vz*x,e,m,fp
end

Function log2 x
log2=Int(Log(x)/Log(2))
End Function



MichaelEdited by twofingers 2014-08-31
 
Print this page


To reply to this topic, you need to log in.

© JAQ Software 2024