Microsoft Extended BASIC, as used by the Dragon, uses a 40 bit (5 byte) float format(*1):
Field Size (Bits)
Exponent Sign 1
Exponent 7
Mantissa Sign 1
Mantissa 31
--
40
Numbers are always normalized with the top mantissa bit removed.
As an oddity, they are stored in a 6 byte structure with the 6th byte unused.
I suspect that the divergence is due to numerical precision,
Most likely, as Microsofts 40 bit format differs from IEEE-754 single (32 Bit) as well as from double (64 bit). Since Python uses double IEEE format, its results will differ in precision and these differences may add up.
In addition, if you use any trigonometric function or square-root, results may wander off even more due to a different approximation.
Some unordered thoughts:
One solution would be to use single precision (with numpy) with your Python solver, as Jean-François Fabre sugsests. But it's still a different precision, so depending on the task the results may still vary a lot.
This could be levelled by 'amputating' the BASIC numbers down to single precision as well by clearing the lowest mantissa byte after each computational assignment. Doing this in BASIC alone will be rather cumbersome (*2), but a quite short machine routine called with USR
will do the trick.
100 A=1+1 : A=USR0(A)
USR
will lookup the variable and move it to the Floating Point Accumulator at $004F and the assignment stores the result in A again. Of course any other variable can be uses as well (*3). Since BASIC is doing most of the Stuff, the machine routine is essentially just two instructions:
B7 53 00 STAA $4F ; Clear the lowest mantissa byte (*4)
39 RTS ; Return to BASIC
Of course this has to be stored somewhere. For routines that short, the 6 unused (*5) bytes at $011A work fine, so the add
10 POKE &H011A,&HB7: POKE &H011B,....
20 DEFUSR0=&H011A
to initialise the USR
function.
(CAVEAT: this is a quick hack from my faint memory while peeking at the memory map).
Of course, this still doesn't solve possible different approximations of build in function. Only precision should now be aligned.
(And sorry for being carried away, it was too tempting :))
*1 - It's the so called Extended Format (sic) added with the 8 KiB extended Basic.
*2 - Or not, as the Dragon knows VATPTR ... so forget all that follows and do simply A=1+1 : POKE VARPTR(A)+4,0
. With preparing the addresses ahead of time (AA=VARPTR(A)+4 ... POKE AA,0
) this might be as fast as the machine language routine :(
*3 - BTW, to speed up calculations it's helpful to define the most used variables first.
*4 - Confused ... well, this is using a neat side effect. BASIC passes the type of the parameter in A - 1 for a string and 0 for a float - so we receive a cleared A, ready to be used :))
*5 - Only with a Dragon 32.