### 9 releases

0.1.8 | Apr 29, 2024 |
---|---|

0.1.7 | Apr 21, 2024 |

0.1.1 | Mar 18, 2024 |

#**483** in Data structures

**564** downloads per month

**ISC**license

29KB

717 lines

# Fix

Fixed-point number types with Solana Anchor support.

## Documentation

###
`lib.rs`

:

Fixed-point number types.

# What?

Fixed-point is a number representation with a fixed number of digits before and after the radix point. This means that range is static rather than dynamic, as with floating-point. It also means that they can be represented as integers, with their scale tracked by the type system.

In this library, the scale of a

is represented as two type-level integers: the base and
the exponent. Any underlying integer primitive can be used to store the number. Arithmetic can
be performed on these numbers, and they can be converted to different scale exponents.`Fix`

# Why?

A classic example: let's sum 10 cents and 20 cents using floating-point. We expect a result of 30 cents.

`assert_eq!``(``0.``30``,` `0.``10` `+` `0.``20``)``;`

Wrong! We get an extra forty quintillionths of a dollar.

`assertion failed: `(left == right)` (left: `0.3`, right: `0.30000000000000004`)'
`

This is due to neither 0.1 nor 0.2 being exactly representable in base-2, just as a third can't
be represented exactly in base-10. With

, we can choose the precision we want in base-10,
at compile-time. In this case, hundredths of a dollar will do.`Fix`

`use` `fix``::``aliases``::``si``::`Centi`;` `//` Fix<_, U10, N2>
`assert_eq!``(``Centi``::`new`(``0_30``)``,` `Centi``::`new`(``0_10``)` `+` `Centi``::`new`(``0_20``)``)``;`

But decimal is inefficient for binary computers, right? Multiplying and dividing by 10 is
slower than bit-shifting, but that's only needed when *moving* the point. With

, this is
only done explicitly with the `Fix`

method.`convert`

`use` `fix``::``aliases``::``si``::``{`Centi`,` Milli`}``;`
`assert_eq!``(``Milli``::`new`(``0_300``)``,` `Centi``::`new`(``0_30``)``.``convert``(``)``)``;`

We can also choose a base-2 scale just as easily.

`use` `fix``::``aliases``::``iec``::``{`Kibi`,` Mebi`}``;`
`assert_eq!``(``Kibi``::`new`(``1024``)``,` `Mebi``::`new`(``1``)``.``convert``(``)``)``;`

It's also worth noting that the type-level scale changes when multiplying and dividing, avoiding any implicit conversion.

`use` `fix``::``aliases``::``iec``::``{`Gibi`,` Kibi`,` Mebi`}``;`
`assert_eq!``(``Mebi``::`new`(``3``)``,` `Gibi``::`new`(``6``)` `/` `Kibi``::`new`(``2``)``)``;`

`no_std`

`no_std`

This crate is

.`no_std`

#### Dependencies

~0.3–10MB

~97K SLoC