![]() |
Forum Index : Microcontroller and PC projects : [MicroMite]Strange Behaviour with 9999999
Author | Message | ||||
G8JCF![]() Guru ![]() Joined: 15/05/2014 Location: United KingdomPosts: 676 |
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: AustraliaPosts: 6223 |
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 |
||||
Geoffg![]() Guru ![]() Joined: 06/06/2011 Location: AustraliaPosts: 3272 |
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 KingdomPosts: 4004 |
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 KingdomPosts: 676 |
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: AustraliaPosts: 3272 |
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 KingdomPosts: 676 |
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 KingdomPosts: 4004 |
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.) John |
||||
twofingers Guru ![]() Joined: 02/06/2014 Location: GermanyPosts: 1533 |
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 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 ![]() Michael causality ≠correlation ≠coincidence |
||||
Geoffg![]() Guru ![]() Joined: 06/06/2011 Location: AustraliaPosts: 3272 |
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: GermanyPosts: 1533 |
Where the glitches starts ... 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 Michael causality ≠correlation ≠coincidence |
||||
![]() |
![]() |
The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |