These tricks are usually done to increase speed or reduce space. For most (especially Microsoft) BASIC, constants are stored within a tokenized line as ASCII (as entered), and converted to a floating point number every time they are evaluated. This is a time consuming process. Assigning the number once to a variable to be used thereafter will skip this part and save quite some time.
Sinclair (Floating Point) BASIC is better than that. While it also includes the number the same way (*1), it is followed by the token 0x0E
(*2), and the next 5 bytes storing the constant in floating point format. Sinclair BASIC does now only need to read past the ASCII until the 0x0E
and take the FP without the need of conversion - so speed is not an issue.
But looking at the encoding shows that every time a constant is used it will take at least 7 bytes of program memory:
A variable name is stored within the program as its ASCII representation. So a two letter name (like on, tw, ...) occupies just two bytes (*3). Thus any occurrence of on
is just two bytes instead of seven. That's five bytes saved each time on
is used.
Of course, this comes with an offset of assigning the variable, which is 5 bytes plus the expression used. So with LET ze=0
that would be 12 bytes, meaning that already using the variable three times will save space.
Using ze=PI-PI
saves even further, as this takes only 3 bytes, so the second usages of ze
will yield saved program space. Similar for all the other calculations. It's all about avoiding constants and replacing them by shorter encoded calculations.
In fact, these optimizations also offer some hints about the age of a program, or at least the time its programmer learned the tricks. PI-PI
was eventually the first discovered and used a lot - until someone came up with the idea of NOT PI
which also results in zero, but needs one byte less. SGN PI
gives one. Two is a bit more complex, but on+on
is as good as SGN PI+SGN PI
(both 5 bytes) - later INT EXP SGN PI
with only 4 bytes was discovered. Three again is just INT PI
, and so on.
The origin of these very Sinclair BASIC specific tricks starts with the ZX81 (the same as the ZX80, but with Floating Point BASIC). Here program space was scarily rare, thus every byte saved was worth the extra effort - much more than later on with the 'huge' RAM the Spectrum offered (*4).
Use of these tricks is a good hint that a programmer started out on a ZX81.
So I'd say that guy did start on a ZX81, and the above program was written early on - and just moved to the Spectrum later.
*1 - Well, not as entered, but as if it had been listed after being converted to float, and back to printable.
*2 - While this structure was introduced with the ZX80 FP BASIC/ZX81, 0x7E was used there. When creating Spectrum BASIC it was changed to 0x0E to allow its character set to be (mostly) ASCII compatible.
*3 - It's a bit more complex, so dig into BASIC tokenization and variable list handling if you really want to know the fine print.
*4 - Then again, we all know that there is never sufficient RAM.
PI
is a keyword, so it is tokenized when the program is entered. At runtime, the execution of that token consists of making a copy of a floating point constant that's somewhere in the BASIC ROM. Numeric literals like0
or1
have no tokenization, so they have to be converted from their source code representation to floating point values at runtime, which makes them slower. (Slower even than a subtraction or a division? I don't know.)