Why does PRINT'ing a true boolean expression output -1?
Asked Answered
P

3

13

In Commodore 64 BASIC V2, PRINT'ing a true boolean expression outputs -1:

READY.
A=(5=5)

READY.
PRINT A
-1

Why -1 and not 1?

enter image description here

Poff answered 9/3, 2014 at 15:29 Comment(2)
true is non-zero, so it doesn't really matter. Technically, a signed, twos-complement binary number with a single bit can be 0 or -1, maybe it's because of that.Mamoun
When calculating 5=5 it returns True because the comparison is equal.Cocoa
C
9

Commodore Basic doesn't have a boolean data type. A boolean expression evaluates to a number, where 0 means False and -1 means true.

As there is no boolean data type there are no boolean type expressions. You can use any numeric expression in an IF statement, and it will interpret any non-zero value as True.

Some languages where a boolean value is numeric or where it can be converted to a numeric value uses -1 to represent a true value. For an integer value 0 all bits are cleared, and for -1 all bits are set, so they can be seen as natural complements for each other.

Eventhough Commodore Basic doesn't use integer numbers but floating point numbers, the value -1 was supposedly chosen because some other languages uses it.

Celebrated answered 9/3, 2014 at 15:33 Comment(5)
Could you clarify the "most languages" part with some examples? Most languages I know use 1, not -1 (and a few use zero, but they are crazy) :)Mamoun
@roe: You are right, more languages than I remembered uses 1 rather than -1. I adjusted the answer accordingly.Celebrated
Commodore Basic DOES use 16 bits integers for storing variables values unless floating point is required because the value to store exceeds the limits of 16 bit integer or has decimalsYadirayaeger
@Yadirayaeger Only variables marked with % as integer variables are stored as 16 bit values. And regardless of the type calculations are done in floating point precision. Scalar variables even take the same memory space regardless of the numerical type, ”wasting” tree bytes per integer scalar variable.Sheffie
@Sheffie you're right. I updated the answer. Thank you.Yadirayaeger
Y
6

Short answer

Why -1 and not 1?

It's just a convention


Some speculation...

The reason underlying the choice for this convention may be related to the internal representation of integers numbers on most platforms:

Suppose a boolean value is stored in a 16 bits wide integer; false is 0 (every bit unset).

0 => 00000000 00000000

It makes sense to agree upon another convention where true is all bits set:

11111111 11111111

(a very reasonable choice since all 1 is the bitwise NOT of all 0)

The decimal representation of a signed integer whose bits are all set is -1

-1 => 11111111 11111111

While the binary representation of 1 is

1 => 00000001 00000000 (on a little endian platform).

So that's why -1 and not 1: is just a convention; but if you look at the binary representation of the value you may agree that the convention makes sense.

However this convention is far from being universally adopted despite all the above considerations. On many languages true casted to a numeric value is 1.


An important note about the code you posted:

You wrote

A=(5=5)

A is a real variable whose value is represented by 5 bytes (1 for exponent, 4 for mantissa).

The internal C64 representation of the real value 0 is all bits 0, but the representation of -1 is far from being all bits 1.

(all bits 1 would lead to the value -1.70141183e+38)

So again C64 Basic just sticks to a convention.


Finally let's explain the behaviuour of the IF statements in your code.

Any value different from 0 is evaluated as true in an IF statement (this happens on most languages, maybe all).


Bottom note:

If you want to take a look at the internal representation of a C64 variable (integer or real only, not strings) you may use the following code:

READY.

10 REM THE VARIABLE TO INSPECT
20 A=(5=5)
30 REM THE ADDR. OF THE FIRST VARIABLE
40 B=PEEK(45)+256*PEEK(46)
50 REM DISPLAY THE VAR'S 7 BYTES
60 FOR C=B TO B+6
70 PRINT C;": ";PEEK(C)
80 NEXT C

RUN
 2227 :  65
 2228 :  0
 2229 :  129
 2230 :  128
 2231 :  0
 2232 :  0
 2233 :  0

Note the first two addresses (2227, 2228) store the variable's name (65, 0 for A)

You may try declaring the variable as integer and see the result with

20 A%=(5=5)
Yadirayaeger answered 10/5, 2014 at 22:53 Comment(2)
In Commodore BASIC, variables and numeric literals are by default 5-byte floating-point, not 2-byte integers. But even bona-fide integers are promoted to floating point during arithmetic evaluation. Your explanation therefore doesn't have much bearing on the example presented in the question.Tereasaterebene
@Tereasaterebene I did some research and you're right. I updated the answer. Thank you.Yadirayaeger
E
2

There is a way that this may be used, by customising a for loop, i.e., if you wanted something to happen until a key is pressed, one might:

0 for i=-1 to 0
1 rem logic here ...
10 get a$: i=(a$=""): next i

This is the same sort of logic as a do...while loop.

Edit - If you specifically wanted 0 to be false and 1 to be true, you could define a function as follows (I forgot about the ABS keyword as I've not used it in probably 20 years :-|) :

0 def fn b(x) = abs(x)
1 i = 7
2 a$ = "hello"
3 if fn b (i=6) then print "i is 6"
4 if fn b (i<10) then print "i is less than 10"
5 if fn b (a$="hi") then print "hey there!"
6 if fn b (a$="hello") then print a$
Erie answered 6/5, 2014 at 10:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.