> ## Documentation Index
> Fetch the complete documentation index at: https://docs.canary.effectiveai.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Exact numbers

> Why an RSL rater calculates with exact decimals, reads each input number exactly as sent, and rounds only where the filing says.

An RSL rater calculates the way an actuary does on paper. `0.1` is exactly one tenth, and
`1.1 + 2.2` is exactly `3.3`. A value changes only at a `round` that the rater writes.

## Why exact numbers matter

A rating manual prints its rates and factors as decimals. Most programs store numbers in binary,
which holds most decimals only approximately. Over a long chain of factors, those small errors
can move a premium by a cent. The result can also depend on the order of the steps.

RSL keeps each value exact through the declared operations. The same implementation and inputs produce the same result across machines.
Calculation order still matters where rounding intervenes. Validate the declared order and rounding rules against the filing and independent examples.

## Inputs arrive exactly

The rater reads each number in a request from its text, so `1000.005` stays `1000.005`. It then
checks the number against its declared precision, and refuses a number off that precision.
Save the following synthetic rater as `exact/rater.rsl` to run the examples:

> [accordion] Complete example: exact/rater.rsl
>
> ```rsl exact/rater.rsl theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
> spec {
>     rsl: "0.4",
>     carrier: "Example Mutual",
>     state: AZ,
>     product: "Guide example",
>     effective_date: 2026-01-01
> }
>
> Sources = {
>     manual: Source = {
>         artifact: artifact("00000000-0000-4000-8000-000000000000"),
>         kind: pdf
>     }
> }
>
> Records = {
>     Policy = {
>         inputs {
>             annual_premium: Num {precision: 0.01} where self in [100, 100000]
>         },
>         monthly: Num = self.annual_premium / 12,
>         installment: Premium [cite: manual:p11] = round(self.monthly, 2, half_up)
>     }
> }
>
> RatingOutcomes = {
>     installment: Policy.installment
> }
> ```

Its `annual_premium` input has a precision of `0.01`. Rate three requests:

```python theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
from decimal import Decimal

from relativities import Rater

rater = Rater.build("exact/rater.rsl")
requests = [{"annual_premium": 1000.005}, {"annual_premium": "1000"}, {"annual_premium": Decimal("1e3")}]
print(rater.rate(requests).to_pandas()[["status", "reason_code", "installment"]])
#            status      reason_code installment
# 0  invalid_inputs  INPUT-PRECISION         NaN
# 1  invalid_inputs       INPUT-TYPE         NaN
# 2       succeeded              NaN       83.33
```

* Send numbers as numbers. A number inside a string is a type error.
* A Python float travels as its shortest decimal text, so `1000.005` arrives as `1000.005`.
* A `Decimal` keeps its own digits. An exponent such as `1e3` names an exact value.
* The rater uses each input as sent. Round an input before you send it.

## Division keeps the exact value

`1000 / 12` is exactly `250/3`. The `monthly` calculation keeps that value, and `installment`
rounds it to cents:

```python theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
print(rater.explain({"annual_premium": 1000}))
#           kind            name  value
# 0        input  annual_premium   1000
# 1  calculation         monthly  250/3
# 2  calculation     installment  83.33
```

`explain` gives a value with a short decimal form as a `Decimal`, and any other value, such as
`250/3`, as a `Fraction`. A premium always rounds, so it always comes back as a `Decimal`.

## A precision on a calculation is a promise

A calculation typed with a precision, such as `Money` in whole cents, promises values on that
precision. The check proves the promise, and the rater rounds only where a `round` says so.
[`E-COMPUTED-RANGE`](https://docs.canary.effectiveai.app/rsl/reference/check-messages/numbers#e-computed-range) shows the message for a
broken promise, and its fix.

## Related

* [Round a premium](https://docs.canary.effectiveai.app/rsl/how-to/round-a-premium.md) shows each rounding mode.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.