Exact Arbitrary-Precision Decimal Vectors

Arbitrary-precision vectors with an exact decimal representation, avoiding the rounding surprises of binary floating point. Built on the 'mpdecimal' C library, arithmetic is governed by an explicit decimal context controlling precision, rounding, and signaling, and vectors integrate with 'vctrs' for use in data frames, 'tibble' objects, summaries, and common numeric workflows. Missing values, signed zeros, infinities, and not-a-number values are supported throughout. The arithmetic model follows Cowlishaw (2009) "General Decimal Arithmetic" < https://speleotrove.com/decimal/decarith.html>.


decimal

R-CMD-check coverage

Overview

decimal provides exact, arbitrary-precision decimal vectors for R. If you’ve ever been surprised that 0.1 + 0.2 == 0.3 is FALSE, this package is for you:

library(decimal)

0.1 + 0.2 == 0.3
#> [1] FALSE
decimal("0.1") + decimal("0.2") == decimal("0.3")
#> [1] TRUE

Doubles are binary fractions, so they can’t represent most decimal numbers exactly, and tiny errors accumulate as you compute. That’s usually fine — but not when you’re working with money, invoices, exchange rates, or anything else where cents have to add up. decimal uses a decimal representation and performs arithmetic under an explicit decimal context, so any rounding is controlled and observable.

Under the hood, decimal is built on:

  • mpdecimal, the battle-tested C library behind Python’s decimal module, implementing the General Decimal Arithmetic standard.

  • vctrs, so decimal vectors work naturally in data frames, tibbles, dplyr::mutate(), joins, sorting, and everything else you already do with vectors.

Highlights:

  • Exact values. Strings and integers are parsed exactly; promotion to a finer shared scale only adds trailing zeros. Values round-trip through as.character() without loss — nothing changes on the way to a CSV file or database column and back.

  • Full arithmetic. +, -, *, /, ^, %%, %/%, comparisons, and math functions like abs(), sqrt(), exp(), and log(), plus reductions sum(), prod(), min(), max(), and mean().

  • Decimal-aware tools. quantize() to round to a fixed number of digits (say, cents), normalize(), fma(), same_quantum(), adjusted(), and number_class().

  • You control the rules. A decimal context sets the precision, rounding mode, and which conditions (overflow, division by zero, …) are errors — see vignette("contexts-and-signals").

  • Special values. NA, signed zeros, infinities, and quiet and signaling NaNs are supported throughout.

Installation

Install the released version from CRAN:

install.packages("decimal")

Usage

Create decimal vectors from strings (exact, and the recommended way) or integers, and use them like any other numeric vector:

library(decimal)

x <- decimal(c("1.20", "2.30", "3.40"))
x
#> <decimal[3]>
#> [1] 1.20 2.30 3.40

sum(x)
#> <decimal[1]>
#> [1] 6.90
mean(x)
#> <decimal[1]>
#> [1] 2.30

Decimal vectors are first-class citizens in tibbles and dplyr pipelines:

library(dplyr)

sales <- tibble::tibble(
  item  = c("coffee", "bagel", "juice"),
  price = decimal(c("2.50", "1.25", "3.95")),
  qty   = c(3L, 2L, 1L)
)

sales |>
  mutate(total = price * qty) |>
  summarise(revenue = sum(total))
#> # A tibble: 1 × 1
#>   revenue
#>     <dec>
#> 1   13.95

Exactness matters most when small errors compound — literally, in the case of interest:

principal <- decimal(c("1000.00", "2500.00", "500.00"))
rate <- decimal("0.05")

balance <- principal * (1L + rate)^4L
balance
#> <decimal[3]>
#> [1] 1215.5062500000 3038.7656250000 607.7531250000

# round to cents for reporting
quantize(balance, decimal("0.01"))
#> <decimal[3]>
#> [1] 1215.51 3038.77 607.75

Learning more

  • vignette("decimal-values") introduces decimal vectors: how to create them, how scale works, and the everyday operations.

  • vignette("contexts-and-signals") covers the arithmetic context: precision, rounding modes, traps, and flags.

  • The General Decimal Arithmetic specification is the standard that mpdecimal implements and this package follows.

License

decimal is MIT licensed. The vendored mpdecimal library retains its own BSD-2-Clause terms; see inst/COPYRIGHTS.

Reference manual

It appears you don't have a PDF plugin for this browser. You can click here to download the reference manual.

install.packages("decimal")

0.1.1 by Pedro Baltazar, 12 days ago


https://github.com/pedrobtz/decimal, https://pedrobtz.github.io/decimal/


Report a bug at https://github.com/pedrobtz/decimal/issues


Browse source code at https://github.com/cran/decimal


Authors: Pedro Baltazar [aut, cre, cph] , Stefan Krah [ctb, cph] (Vendored 'mpdecimal' library in src/mpdecimal; see inst/COPYRIGHTS.)


Documentation:   PDF Manual  


MIT + file LICENSE license


Imports methods, rlang, vctrs, withr

Suggests arrow, covr, data.table, dplyr, knitr, pillar, R6, rmarkdown, tibble, testthat


See at CRAN