# Day 18: Floating-Point Arithmetic

We have already covered using fixed-point for fractional numbers, but there may be times when you absolutely require true floating-point, so guess what we’re gonna look at now.

## OP Registers

A bit of a misnomer, since the OP registers are really sections of RAM. There are six OP RAM registers: OP1 to OP6. They are used mainly for two things:

- Storing floating-point numbers.
- Holding variable names.

Each OP register is eleven bytes in length. This is because variable names and floating-point numbers are formatted to be 9 bytes in size. Bytes 10 and 11 are used for extra precision in floating-point numbers when doing math.

## Floating-Point Numbers

Well, we *are* dealing with a calculator after all :).

TI stores floating point numbers according to this structure:

```
struct FP {
byte sign; // Whether the number is positive or negative
byte exponent; // Locates the decimal point
byte significand[7]; // The number itself
byte guard[2]; // Guard digits for mathematics
};
```

The magnitude of every real number except zero can be represented as *m*
× 10^{exp}, where *exp* is an integer designating the exponent and *m*
is a real number designating the significand such that 1 <= *m* < 10.

### Sign

This byte determines if the number evaluates as positive or negative,
and also if it is real or complex. For the uninitiated, a complex number
is one of the form a+b*i*, where *i* is the square root of -1.

- %00000000 — Positive and real.
- %10000000 — Negative and real.
- %00001100 — Positive and complex.
- %10001100 — Negative and complex.

### Exponent

The exponent field reports the power of ten that the mantissa is to be
raised. The number format is not the usual two’s complement, but rather
biased to $80. A value of $80 translates as 10^{0}. $81 is 10^{1}.
$7F is 10^{-1}.

### Significand

These are the digits of the number. Each nibble specifies one decimal digit, so you can have a floating-point number with 14 digits. The first digit, and only the first digit, is the characteristic (the whole part) with the remainder being the mantissa (the decimal part).

Examples:

`$00, $9E, $23, $91, $80, $55, $75, $00, $00`

: 2.391805575 × 10^{30}`$80, $AC, $46, $19, $18, $45, $80, $00, $00`

: -4.61918458 × 10^{44}`$80, $77, $75, $16, $99, $60, $94, $17, $87`

: -7.5169960941787 × 10^{-7}`$00, $89, $19, $80, $61, $22, $02, $65, $10`

: 1980612202.6510

If the number is complex, then this number is the real part (*a*). The
imaginary part (*b*) is held in the next consecutive OP register, which
also has bits 2 and 3 of its sign byte set.

Example:

`$0C, $7E, $22, $09, $78, $47, $30, $00, $00`

`$8C, $7D, $12, $56, $55, $62, $00, $00, $00`

0.0220978473 - 0.0012565562i

## Loading Floating-Point Numbers

To load floating-point (hereafter, ‘FP’) numbers into the OP registers,
you use the `Mov9ToOPx`

system routine.

**: Moves the nine bytes at**

`_Mov9ToOP1`

`HL`

to `OP1`

.- Input
`HL`

- Pointer to start of the nine bytes.

- Destroys
- all but
`A`

For complex numbers, use `_Mov9OP1OP2`

, which moves the 18 bytes at `HL`

to `OP1`

and `OP2`

.

**: Same as _Mov9ToOP1, but moves to**

`_Mov9ToOP2`

`OP2`

.This is what you do:

Example: Store *e* into OP1.

```
LD HL, exp
bcall(_Mov9ToOP1)
RET
exp: .DB $00, $80, $27, $18, $28, $18, $28, $45, $94 ;2.7182818284594
```

## FP Math

What can I say…there are a *lot* of ROM calls for FP math. Here is
just a sampling.

All registers are destroyed. Result returned to OP1.

**: Adds**

`_FPAdd`

`OP2`

to `OP1`

.**: Divides**

`_FPDiv`

`OP1`

by `OP2`

.**: Multiplies**

`_FPMult`

`OP1`

by `OP2`

.**: Reciprocal of**

`_FPRecip`

`OP1`

. `OP2`

= input `OP1`

.**: Subtracts**

`_FPSub`

`OP2`

from `OP1`

.**: Square root of**

`_SqRoot`

`OP1`

.**: Gets a random number. 0.0 >**

`_Random`

`OP1`

> 1.0## Manipulating OP Registers

**: Stores 11 bytes at**

`_OPxToOPy`

`OPx`

to `OPy`

.- Destroys
`BC DE HL`

These combinations are available:

`x` \ `y` |
OP1 | OP2 | OP3 | OP4 | OP5 | OP6 |
---|---|---|---|---|---|---|

OP1 | x | x | x | x | x | |

OP2 | x | x | x | x | x | |

OP3 | x | x | x | x | ||

OP4 | x | x | x | x | x | |

OP5 | x | x | x | x | x | |

OP6 | x | x | x |

**: Swaps 11 bytes at**

`_OPxExOPy`

`OPx`

with 11 bytes at `OPy`

.- Destroys
`A BC DE HL`

These combinations are available:

`x` \ `y` |
OP2 | OP3 | OP4 | OP5 | OP6 |
---|---|---|---|---|---|

OP1 | x | x | x | x | |

OP2 | x | x | x | ||

OP5 | x |

## Displaying FP Numbers

**: Displays the floating-point number in**

`_DispOP1A`

`OP1`

using the small font, formatted using the current FIX setting.- Input
`OP1`

- Number
`A`

- Maximum number of characters (not digits) to display.

- Destroys
- All

**: Converts the number in**

`_FormReal`

`OP1`

into a string.- Input
`OP1`

- Number
`A`

- Maximum number of characters (not digits) to display, minimum of six.

- Output
`BC`

- Length of string
`OP3`

- Start of string, null-terminated.

- Destroys
- All

SCI, ENG, and FIX settings affect the string conversion. To ignore all
format settings, use `FormEReal`

.

**: Converts the number in**

`_ConvOP1`

`OP1`

into a two-byte integer.- Input
`OP1`

- Number

- Output
`DE`

- Converted number.

Generates an error if the exponent is greater than 3.