I'm failing to find a concise document that describes the formatting used by (6502) MS BASIC when converting internal floating-point numbers to text for display in PRINT, STR$, etc.

I know it has a leading - or space for +, so for testing, I punted and used sprintf(str, "% -f", a);, but that has some rather common edge cases and now I'd like to implement the canonical solution.


I managed to dig into the code (specifically the FOUT function), and my findings are as follows:

The 6502 Microsoft BASIC interpreter comes in two flavours, which I am going to call 32-bit builds and 40-bit builds; the name comes from the interpreter’s internal floating-point precision. The relevance of this for the number formatting algorithm is that the value of the constant N mentioned below is 6 in 32-bit builds, and 9 in 40-bit builds. Checking whether you’re using a 32-bit or 40-bit build is easy: just ask it to print 106. 32-bit builds will output 1E+06, while 40-bit builds will output 1000000. As far as I am aware, most Microsoft BASIC versions are 40-bit builds.

The formatting algorithm itself is as follows:

  1. Output a sign character: ‘-’ if negative, a space otherwise. The rest of the algorithm operates on the absolute value.

  2. If the number is zero, output ‘0’ and exit. (I failed at making the interpreter ever produce a negative zero, although one can be represented in the underlying format.) The rest of the algorithm operates on positive numbers.

  3. If the number is smaller than 1, multiply it by 10N and initialise the order-of-magnitude counter to −N. Otherwise initialise it to zero. (While this may seem otherwise redundant to the next step, I assume this is a speed and/or precision optimisation.)

  4. Adjust the order-of-magnitude counter by repeating the following steps:

    1. While the number is smaller than 10N − 1 − 0.0501 (*), multiply the number by 10 and decrement the counter.
    2. While the number is larger by 10N − 0.501 (*), divide the number by 10 and increment the counter.
    3. If neither, continue to the next point.
  5. Add ½ to the number and compute its floor. The integer obtained will serve as the significand to display.

  6. If the order-of-magnitude counter is in the range [−(N + 1), 1) (in other words, the absolute value of the original number is in the range [0.01, 10N)), output the number in the ordinary decimal format. Pure integers are output without a decimal point; pure fractions are output without a leading zero (e.g. ½ is .5).

  7. Otherwise, output the number in the exponential format: one leading digit, followed by an optional decimal point, then at most N − 1 fractional digits, the letter ‘E’, the sign (‘+’ or ‘-’) and two-digit magnitude of the exponent.

(*) Subject to approximation; the actual values are 99 999.9375 and 999 999.4375 for 32-bit builds, or 99 999 999.90625 and 999 999 999.25 for 40-bit builds.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.