Crates.io | cpc |
lib.rs | cpc |
version | 1.9.3 |
source | src |
created_at | 2020-08-20 08:52:03.002072 |
updated_at | 2023-09-20 04:24:30.537594 |
description | evaluates math expressions, with support for units and conversion between units |
homepage | https://github.com/probablykasper/cpc#readme |
repository | https://github.com/probablykasper/cpc |
max_upload_size | |
id | 278544 |
size | 219,813 |
calculation + conversion
cpc parses and evaluates strings of math, with support for units and conversion. 128-bit decimal floating points are used for high accuracy.
It also lets you mix units, so for example 1 km - 1m
results in 999 Meter
.
Install using cargo
:
cargo install cpc
To install it manually, grab the appropriate binary from the GitHub Releases page and place it wherever you normally place binaries on your OS.
cpc '2h/3 to min'
Add cpc
as a dependency in Cargo.toml
.
use cpc::eval;
use cpc::units::Unit;
match eval("3m + 1cm", true, Unit::Celsius, false) {
Ok(answer) => {
// answer: Number { value: 301, unit: Unit::Centimeter }
println!("Evaluated value: {} {:?}", answer.value, answer.unit)
},
Err(e) => {
println!("{e}")
}
}
3 + 4 * 2
8 % 3
(4 + 1)km to light years
10m/2s * 5 trillion s
1 lightyear * 0.001mm in km2
1m/s + 1mi/h in kilometers per h
round(sqrt(2)^4)! liters
10% of abs(sin(pi)) horsepower to watts
cpc uses 128-bit Decimal Floating Point (d128) numbers instead of Binary Coded Decimals for better accuracy. The result cpc gives will still not always be 100% accurate. I would recommend rounding the result to 20 decimals or less.
It's pretty fast and scales well. In my case, it usually runs in under 0.1ms. The biggest performance hit is functions like log()
. log(12345)
evaluates in 0.12ms, and log(e)
in 0.25ms.
To see how fast it is, you can pass the --verbose
flag in CLI, or the verbose
argument to eval()
.
Install Rust.
Run cpc with a CLI argument as input:
cargo run -- '100ms to s'
Run in verbose mode, which shows some extra logs:
cargo run -- '100ms to s' --verbose
Run tests:
cargo test
Build:
cargo build
Nice resources for adding units:
In src/units.rs
, units are specified like this:
pub enum UnitType {
Time,
// etc
}
// ...
create_units!(
Nanosecond: (Time, d128!(1)),
Microsecond: (Time, d128!(1000)),
// etc
)
The number associated with a unit is it's "weight". For example, if a second's weight is 1
, then a minute's weight is 60
.
Make sure to also add a test for each unit. The tests look like this:
assert_eq!(convert_test(1000.0, Meter, Kilometer), 1.0);
Basically, 1000 Meter == 1 Kilometer.
Text is turned into tokens (some of which are units) in lexer.rs
. Here's one example:
// ...
match string {
"h" | "hr" | "hrs" | "hour" | "hours" => tokens.push(Token::Unit(Hour)),
// etc
}
// ...
rust_decimal
: Only supports numbers up to ~1E+29bigdecimal
: Lacking math functionsCHANGELOG.md
Cargo.toml
cargo test
v#.#.#
cargo publish