# `Feel.Type.ExactNumber`
[🔗](https://github.com/FeeJai/BDM/blob/feel-v0.1.0/apps/feel/lib/feel/type/exact_number.ex#L1)

Numbers worked on without rounding (D-109).

A `Decimal` is a whole number over a power of ten, and the arithmetic of the `Decimal` library rounds to the
precision of a context (28 digits). The analysis of the amounts of a duration and of the days of a date needs
the exact floor of a quotient, and a comparison of bounds that are as large as a number can be, so it works on
`{numerator, scale}`, which is `numerator / 10^scale`, with Elixir's integers, which have no limit.

    iex> x = Feel.Type.ExactNumber.fraction(Decimal.new("-2.5"))
    iex> {x, Feel.Type.ExactNumber.floor_of(x), Feel.Type.ExactNumber.ceiling_of(x)}
    {{-25, 1}, -3, -2}
    iex> Feel.Type.ExactNumber.floor_div(Feel.Type.ExactNumber.fraction(Decimal.new("86399.5")), 86_400)
    0

# `t`

```elixir
@type t() :: {integer(), non_neg_integer()}
```

`{numerator, scale}`: the number `numerator / 10^scale`.

# `add`

```elixir
@spec add(t(), t()) :: t()
```

The sum of two exact numbers.

# `ceiling_div`

```elixir
@spec ceiling_div(t(), pos_integer()) :: integer()
```

The ceiling of the number over a whole number above zero.

# `ceiling_of`

```elixir
@spec ceiling_of(t()) :: integer()
```

The least whole number not below the number.

# `compare`

```elixir
@spec compare(t(), t()) :: :lt | :eq | :gt
```

# `decimal`

```elixir
@spec decimal(integer(), non_neg_integer()) :: Decimal.t()
```

The `Decimal` of an exact number, with no zero at the end of its fraction, so that the same number is the same term
(`0.50` is `0.5` and `1.0` is `1`). A whole number of more than 34 digits is written with an exponent, as a number
of FEEL is (`fit/2` gives `{5 * 10^6000, 0}` for a bound of that size, and `Decimal.new(1, 5 * 10^6000, 0)` is not a
number the run takes, D-59): its zeros are the exponent, so that it is `5E+6000`, as the literal is.

    iex> Feel.Type.ExactNumber.decimal(50, 2)
    Decimal.new("0.5")
    iex> Feel.Type.ExactNumber.decimal(10, 1)
    Decimal.new(1)
    iex> Feel.Type.ExactNumber.decimal(0, 5)
    Decimal.new(0)
    iex> Feel.Type.ExactNumber.decimal(100, 0)
    Decimal.new(100)
    iex> Feel.Type.ExactNumber.decimal(-5 * Integer.pow(10, 40), 0)
    Decimal.new("-5E+40")

# `fit`

```elixir
@spec fit(t(), :down | :up) :: t()
```

The number rounded to 34 significant digits, as a number of FEEL is (the run rounds the seconds between two times, and
the `value` of a date and time, to that), in the direction given: `:down` for a lower bound, `:up` for an upper one,
so that what the run rounds to (half to even, to the nearest) is between them.

    iex> alias Feel.Type.ExactNumber, as: E
    iex> E.fit({12_345_678_901_234_567_890_123_456_789_012_345_678, 4}, :down)
    {1_234_567_890_123_456_789_012_345_678_901_234, 0}
    iex> E.fit({12_345_678_901_234_567_890_123_456_789_012_345_678, 4}, :up)
    {1_234_567_890_123_456_789_012_345_678_901_235, 0}
    iex> E.fit({5, 1}, :up)
    {5, 1}

# `floor_div`

```elixir
@spec floor_div(t(), pos_integer()) :: integer()
```

The floor of the number over a whole number above zero.

# `floor_of`

```elixir
@spec floor_of(t()) :: integer()
```

The greatest whole number not above the number.

# `fraction`

```elixir
@spec fraction(Decimal.t()) :: t()
```

The exact number that a `Decimal` is.

# `greater`

```elixir
@spec greater(t(), t()) :: t()
```

The greater of two exact numbers.

# `lesser`

```elixir
@spec lesser(t(), t()) :: t()
```

The lesser of two exact numbers.

# `negate`

```elixir
@spec negate(t()) :: t()
```

# `subtract`

```elixir
@spec subtract(t(), t()) :: t()
```

The difference of two exact numbers.

# `trailing_zeros`

```elixir
@spec trailing_zeros(String.t()) :: non_neg_integer()
```

The number of `0` at the end of the digits of a whole number that is not zero (its first digit is not `0`), found by
halving: a run of 6,000 zeros, as the bound `max` of the numbers of FEEL has when a preimage is written back as a
`Decimal`, is about 13 comparisons of a binary, and `String.trim_trailing/2` took 6,000 steps for it, twice for each
fact of a rounding function. The last `m` digits are all `0` for every `m` up to the number of zeros and for none
above it, and that is what is searched for.

    iex> Feel.Type.ExactNumber.trailing_zeros("12300")
    2
    iex> Feel.Type.ExactNumber.trailing_zeros("7")
    0
    iex> Feel.Type.ExactNumber.trailing_zeros("1" <> String.duplicate("0", 6000))
    6000

# `unify`

```elixir
@spec unify(t(), t()) :: {integer(), integer(), non_neg_integer()}
```

Two exact numbers over the same power of ten: `{first, second, scale}`.

# `whole`

```elixir
@spec whole({t(), :open | :closed}, {t(), :open | :closed}) ::
  {integer(), integer()} | nil
```

The first and the last whole number of an interval `low..high`, where each end is in (`:closed`) or not (`:open`),
or `nil` if it has none.

    iex> alias Feel.Type.ExactNumber, as: E
    iex> E.whole({E.fraction(Decimal.new("0.5")), :closed}, {E.fraction(Decimal.new(3)), :open})
    {1, 2}
    iex> E.whole({E.fraction(Decimal.new(1)), :open}, {E.fraction(Decimal.new(2)), :open})
    nil

---

*Consult [api-reference.md](api-reference.md) for complete listing*
