18 releases

Uses old Rust 2015

0.4.3 Mar 5, 2024
0.4.2 Oct 16, 2023
0.4.1 Jul 13, 2023
0.3.0 Aug 26, 2021
0.0.7 May 2, 2017

#2 in Math

Download history 197242/week @ 2023-11-26 178893/week @ 2023-12-03 179491/week @ 2023-12-10 186249/week @ 2023-12-17 93447/week @ 2023-12-24 139381/week @ 2023-12-31 172692/week @ 2024-01-07 175882/week @ 2024-01-14 197442/week @ 2024-01-21 201492/week @ 2024-01-28 200548/week @ 2024-02-04 194638/week @ 2024-02-11 169832/week @ 2024-02-18 201926/week @ 2024-02-25 199472/week @ 2024-03-03 86445/week @ 2024-03-10

667,009 downloads per month
Used in 682 crates (226 directly)

MIT/Apache

255KB
6K SLoC

bigdecimal-rs

crate Documentation

minimum rustc 1.43

codecov build status - master build status - trunk

Arbitrary-precision decimal numbers implemented in pure Rust.

Community

Join the conversation on Zulip: https://bigdecimal-rs.zulipchat.com

Please share important stuff like use-cases, issues, benchmarks, and naming-convention preferences.

This project is currently being re-written, so if performance or flexibility is lacking, check again soon and it may be fixed.

Usage

Add bigdecimal as a dependency to your Cargo.toml file:

[dependencies]
bigdecimal = "0.4"

Import and use the BigDecimal struct to solve your problems:

use bigdecimal::BigDecimal;

fn main() {
    let two = BigDecimal::from(2);
    println!("sqrt(2) = {}", two.sqrt().unwrap());
}

this code will print

sqrt(2) = 1.414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641573

Compile-Time Configuration

You can set a few default parameters at compile-time via environment variables:

Environment Variable Default
RUST_BIGDECIMAL_DEFAULT_PRECISION 100
RUST_BIGDECIMAL_DEFAULT_ROUNDING_MODE HalfEven
RUST_BIGDECIMAL_EXPONENTIAL_FORMAT_THRESHOLD 5

These allow setting the default Context fields globally without incurring a runtime lookup, or having to pass Context parameters through all calculations. (If you want runtime control over these fields, you will have to pass Contexts to your functions.) Examine build.rs for how those are converted to constants in the code (if interested).

Default precision

Default precision may be set at compile time with the environment variable RUST_BIGDECIMAL_DEFAULT_PRECISION. The default value of this variable is 100.

This will be used as maximum precision for operations which may produce infinite digits (inverse, sqrt, ...).

Note that other operations, such as multiplication, will preserve all digits; so multiplying two 70 digit numbers will result in one 140 digit number. The user will have to manually trim the number of digits after calculations to reasonable amounts using the x.with_prec(30) method.

A new set of methods with explicit precision and rounding modes is being worked on, but even after those are introduced the default precision will have to be used as the implicit value.

Rounding mode

The default Context uses this value for rounding. Valid values are the variants of the RoundingMode enum.

Defaults to HalfEven.

Exponential Format Threshold

The maximum number of leading zeros after the decimal place before the formatter uses exponential form (i.e. scientific notation).

There is currently no mechanism to change this during runtime. If you know of a good solution for number formatting in Rust, please let me know!

Example Compile time configuration

Given the program:

fn main() {
    let n = BigDecimal::from(700);
    println!("1/{n} = {}", n.inverse());
}

Compiling with different environment variables prints different results

$ export BIG_DECIMAL_DEFAULT_PRECISION=8
$ cargo run
1/700 = 0.0014285714

$ export RUST_BIGDECIMAL_DEFAULT_PRECISION=5
$ cargo run
1/700 = 0.0014286

$ export RUST_BIGDECIMAL_DEFAULT_ROUNDING_MODE=Down
$ cargo run
1/700 = 0.0014285

$ export RUST_BIGDECIMAL_EXPONENTIAL_FORMAT_THRESHOLD=2
$ cargo run
1/700 = 1.4285E-3

[!NOTE] These are compile time environment variables, and the BigDecimal library is not configurable at runtime via environment variable, or any kind of global variables, by default.

This is for flexibility and performance.

About

This repository contains code originally meant for a bigdecimal module in the popular num crate, but was not merged due to uncertainty of what the best design for such a crate should be.

License

This code is dual-licensed under the permissive MIT & Apache 2.0 licenses.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Dependencies

~0.8–1MB
~23K SLoC