Write down that the left operand decides integer or float arithmetic
No behaviour change, by decision. `A# * 0.45` is 0 and `0.45 * A#` is 1.35, because every operator branches on `self->valuetype` and converts the right operand to match. It is inherited from the Go reference, a C128 promotes to float instead, and this interpreter is at least consistent about it -- so a dialect saying the left operand wins is a defensible position, and changing it to promotion would alter the result of every mixed expression in every existing program. **The defect was that nobody said so.** Chapter 3's "Numbers" did not mention it, Chapter 13 did not list it among the differences, and nothing fails when a program gets it wrong -- it computes something else and carries on. The game in examples/ lost its per-level speed increase to `5.6 + LEVEL# * 0.45` evaluating to a flat 5.6, and bled velocity out of every bounce through `0 - BLVX%(B#)` quantising to whole pixels. Both read correctly. Neither produced a diagnostic. Now said in three places: a section in Chapter 3 with the demonstration and the two rules that keep a program out of it (put the float on the left, put the answer somewhere with a `%` on it), a row in Chapter 13 naming it as the difference from 7.0 most likely to turn a working listing into a quietly wrong one, and the reasoning on value.h where the operators are declared. tests/value_arithmetic.c pins it in both directions across multiply and subtract, with a comment saying it is the documented contract rather than an accident -- so promotion becomes a decision somebody takes deliberately rather than a change that could slip in under a passing suite. TODO.md section 9 item 4, struck as a documentation outcome. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -49,6 +49,36 @@ Literals may be written in hexadecimal with a `0x` prefix. A leading zero is *no
|
||||
octal — `010` is ten, because a leading zero in a listing is far more often padding
|
||||
than a base.
|
||||
|
||||
### The left operand decides whether the arithmetic is integer or float
|
||||
|
||||
**Not the wider of the two, and not the destination.** An integer on the left of an
|
||||
operator converts the right-hand side to an integer, which throws away its fraction:
|
||||
|
||||
```basic
|
||||
A# = 3
|
||||
PRINT A# * 0.45
|
||||
PRINT 0.45 * A#
|
||||
```
|
||||
|
||||
```output
|
||||
0
|
||||
1.350000
|
||||
```
|
||||
|
||||
That is the same expression written the other way round, and the answers differ by
|
||||
everything. A C128 promotes to float instead; this interpreter does not, and it is
|
||||
consistent about it — see [Chapter 13](13-differences.md).
|
||||
|
||||
**Nothing fails when you get it wrong.** The program computes something else and carries
|
||||
on, which is what makes it worth learning early rather than meeting later. Two rules keep
|
||||
you out of it:
|
||||
|
||||
- **Put the float on the left.** `0.45 * LEVEL#`, not `LEVEL# * 0.45`. Likewise
|
||||
`0.0 - V%` rather than `0 - V%` to negate a float, which is otherwise quantised to a
|
||||
whole number.
|
||||
- **Put the answer somewhere that can hold it.** A float expression assigned to a `#`
|
||||
variable truncates: `T# = 4.2 / 5.6` is `0`.
|
||||
|
||||
## Strings
|
||||
|
||||
Strings are up to 255 characters and are written in double quotes. There is no
|
||||
|
||||
Reference in New Issue
Block a user