LOG
| BASIC keyword | |
| Keyword: | LOG |
| Abbreviation: | – |
| Type: | Function |
| Token code: | 188/$BC |
| Handling routine in BASIC ROM: |
47594–47655 $B9EA–BA27 |
| List of all BASIC keywords | |
Remark: This article describes the BASIC command LOG in BASIC V2 at the Commodore 64.
Typ: Numeric Function General Programming-Syntax: LOG(<Numeric>)
The mathematical function LOG is a natural logarithm with the basis e(E). If the term is 0 or negative the BASIC error ?ILLEGAL QUANTITY ERROR IN line occurs. When the number is over 1.7014118342E+38 the BASIC-error ?OVERFLOW ERROR IN line appears. When the numeric argument is absent, a ?SYNTAX ERROR IN line appears.
Examples[edit | edit source]
PRINT LOG(1) Result: 0
PRINT LOG(10) Result: 2.30258509
PRINT LOG(100)/LOG(10) Result: 2
because you can divide by LOG(10) and get a result with the base "10".
Implementation[edit | edit source]
Let the parameter be X. The LOG function first separates the exponent of X from the significand. That is, it calculates two numbers, N and XF, such that:
- X = 2N * XF, N is an integer and 0.5 <= XF < 1.0
C programmers will recognize this separation as the frexp() function.
The natural logarithm is tricky to calculate accurately. The Taylor series converges too slowly to be useful. The BASIC implementation uses a faster approach. Given XF calculated above, it calculates:
- T = 1.0 - sqrt(2.0) / (XF + sqrt(0.5))
It then applies the polynomial approximation:
- 0.43425594189 * T7 + 0.57658454124 * T5 + 0.96180075919 * T3 + 2.8853900731 * T - 0.5
The result of this approximation is log2(XF).
The routine then adds N to that approximation, resulting in log2(X). Finally, it multiplies by LOG(2), giving the final result of LOG(X).
Derivation[edit | edit source]
The developers most likely got the polynomial from Computer Approximations by John Fraser Hart et al. (ISBN 0-88275-642-7). No known source of the Commodore BASIC references this work, but the released GW-BASIC source does mention it. The book specifies polynomial 2662 to approximate the natural logarithm; its exact value is as follows:
- 0.301003281 * x7 + 0.39965794919 * x5 + 0.666669484507 * x3 + 1.9999999937438 * x
This polynomial in fact approximates 2*atanh(x). The ROM contains these coefficients multiplied by the base-2 logarithm of e, to change the base of the logarithm from e to 2.
The polynomial is specified to be used with (x-1)/(x+1), where x is the number for which a logarithm is sought. x may be in the interval [sqrt(0.5), sqrt(2)]; but we want to have x in the interval [0.5, 1]. To get x in the correct interval, it is multiplied by sqrt(2). The free variable for the polynomial then becomes (sqrt(2)*x-1)/(sqrt(2)*x+1), which rearranges to 1 - (sqrt(2)/(x+sqrt(0.5))) as coded in the ROM.
Because x is multiplied by sqrt(2), the result of the polynomial is the desired logarithm plus 0.5. This constant is subtracted from the result.
Accuracy[edit | edit source]

The graph to the right was obtained by comparing results from the BASIC LOG function to values computed on a modern x86-type PC.
At least for the plotted domain of (0,+5], LOG mostly matches the true value to 29 bits. Accuracy degrades around X equal to 1, where LOG(X) is close to 0. Better accuracy could be obtained by switching to the linear approximation log x = x-1 for x between 0.9 and 1.1.
LOG calls POLY1, which calls MLTPLY ($BA59), and consequently the multiply bug affects its results. A small number of input values give results that match to only 24 bits.
ABS | AND | ASC | ATN | CHR$ | CLOSE | CLR | CMD | CONT | COS | DATA | DEF | DIM | END | EXP | FN | FOR | FRE | GET | GET# | GOSUB | GOTO | IF | INPUT | INPUT# | INT | LEFT$ | LEN | LET | LIST | LOAD | LOG | MID$ | NEW | NEXT | NOT | ON | OPEN | OR | PEEK | π | POKE | POS | PRINT | PRINT# | READ | REM | RESTORE | RETURN | RIGHT$ | RND | RUN | SAVE | SGN | SIN | SPC | SQR | STATUS/ST | STEP | STOP | STR$ | SYS | TAB | TAN | THEN | TIME/TI | TIME$/TI$ | TO | USR | VAL | VERIFY | WAIT