There is an interesting value you can get in BASIC, which exposes a bug and offers an insight into how numbers are stored within Petit Computer.

Z=FLOOR(-524287.5) or Z=&H80000 or Z=&B10000000000000000000 (that's 19 zeroes) will set the variable Z to this value. ?Z will show -0. Interestingly, ?-Z will also show -0. ?Z*1 gives the result Overflow (?), as does ?1*Z, ?Z+0, ?0+Z, ?Z-0, and ?Z/1.

Petit Computer stores all numbers as a 2s-complement signed 32-bit fixed-point (as opposed to floating-point) value with a particular format, probably to prevent unexpected results from occurring when using bitwise operators like AND and XOR. 12 bits of precision are assigned to fractional values, thus, a value v is really represented as (v * 4096).

(Interestingly, since Petit Computer only allots 12 bits for the fractional value, it can only store the noninteger part of a number in units of 1/4096. A simple two-line program can demonstrate this:

M=1/4096:IF (M*4096)==1 THEN PRINT "1/4096 is calculated precisely"
N=1/4097:IF N==0 THEN PRINT "1/4097 is rounded to zero"

This program will print both lines, showing that 'epsilon', the smallest nonzero value that SmileBasic can handle, is 1/4096.)

Here's an example of how a typical number might be stored, in this case -250.125 (multiplied by 4096, this gives 1024512, or in binary, 1111 1010 0010 0000 0000):

      1111 1111 1111 0000 0101  1110 0000 0000
      \----------------------/  \------------/
                  |                    |
   integer part (rounded down)  fractional part

The advantage of 2s complement representation is that signed numbers can be added with the same binary rules as unsigned numbers, the only difference being detection of overflows. The disadvantage is an asymmetry in the numbers represented: one more negative number can be represented than positive numbers (e.g. in 8-bit signed arithmetic, you can represent numbers from -128 to 127 inclusive). A side-effect of this is that if you do the 2s complement operation for negating a number (flip all the bits, then add 1), this will work for all numbers except -128... if you try it on -128 you get... -128. This is obviously somewhat unsatisfying, but most software engineers have come to terms with this quirk. Part of the reason for this acceptance is because if you try to work around it, it's all too easy to leave a loophole... exactly as the designers of Petit Computer did.

The FLOOR operation simply clears the last 12 bits of the representation of the number. This will always have the effect of transforming the number to the next lowest integer, if it is not an integer already.

The bit breakdown for the value 524287.5 is as follows:

  0111 1111 1111 1111 1111  1000 0000 0000
  \----------------------/  \------------/
              |                    |
        integer part        fractional part

-524287.5, then, is:

  1000 0000 0000 0000 0000  1000 0000 0000
  \----------------------/  \------------/
              |                    |
        integer part        fractional part

The floor of this value is:

  1000 0000 0000 0000 0000  0000 0000 0000
  \----------------------/  \------------/
              |                    |
        integer part        fractional part

By the rules of 2s complement arithmetic, this is really the value -524288. This is the one value on which negation will not work, you cannot represent the positive value 524288 with this format. Negating this binary representation gives the same binary representation (which is why both ?Z and ?-Z both produce the same result).

The value -524288 cannot be generated by the arithmetic operators: subtraction, e.g. -524287-1, or multiplication, e.g. -262144*2, will cause an Overflow error.

Other results from the interpreter's math operations (after assigning -0 to Z) are as follows:

  • Z==0 gives 0 (false)
  • Z<0 gives 1 (true)
  • NOT Z gives 524287
  • Z/2 gives -262144
  • Z%3 = -2
  • Z OR 1 = -524287
  • HEX$(Z) = "80000"
  • ABS(Z) = -0 (the only time ABS will give a negative result)
  • SGN(Z) = -1
  • EXP(Z) = 0 (but then, -36909/4096 and all lower values give 0)
  • DEG(Z) = 369214.3505859
  • ATAN(Z) = -1.5708078, which is -PI()/2.
  • ATAN(0,Z) = 3.14160156
  • ATAN(Z,0) = -1.57080078
  • ATAN(Z,Z) = -2.35620117, which is -PI()*3/4
  • POW(Z,1) gives -0
  • SIN(Z), COS(Z), TAN(Z), and the two-parameter ATAN with Z as either parameter (except as shown above) will crash the application with no warning.

IAmAPersson made the CrashPTC application which utilizes this glitch.

For another bug with some similar properties, see 524287.999755859375 (Numerical Value), and for another interesting numerical bug, see 0.999995 (Numerical Value).