calculation + conversion
cpc calculates complex strings of math, with support for units and conversion. 128-bit decimal floating points are used for high accuracy.
For example 1tonne * 1sqm / 2second^3 / 5ampere results in 100 volts.
Try it out at cpc.kasper.space
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'
cpc
> sin(1)
≈ 0.84147098480789650665250232163029899962
3 + 4 * 2
6'3" to cm
1tonne * 1sqm / 2s^3 / 5a
(7 % 4)km to light years
10m/2s * 5 trillion s
1 lightyear * 0.001mm in km2
1m/s + 1mi/5h in kilometers per h
round(sqrt(2)^4)! liters
10% of abs(sin(pi)) horsepower to watts
- Normal numbers
- Area
- Currency
- Digital storage (bytes etc)
- Electric current
- Energy
- FLOPS
- Frequency
- Length
- Mass
- Power
- Pressure
- Resistance
- Speed
- Temperature
- Time
- Voltage
- Volume
Add cpc as a dependency in Cargo.toml.
use cpc::eval;use cpc::units::Unit;matcheval("3m + 1cm",true,false){Ok(answer) => {// answer: Number { value: 301, unit: Unit::Centimeter }println!("Evaluated value: {} {:?}", answer.value, answer.unit)},Err(e) => {println!("{e}")}}Inexact results are always indicated with ≈. 128-bit Decimal Floating Point (d128) numbers are used for high accuracy, and prevents most floating-point errors.
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:
- https://wolframalpha.com
- https://github.com/ryantenney/gnu-units/blob/master/units.dat
- https://support.google.com/websearch/answer/3284611 (unit list)
- https://translatorscafe.com/unit-converter (unit conversion)
- https://calculateme.com (unit conversion)
- https://wikipedia.org
In src/units.rs, units are specified like this:
pubenumUnitType{Time,// etc}// ...create_units!(Nanosecond:(Time, d!(1),"nanosecond","nanoseconds"),Microsecond:(Time, d!(1000),"microsecond","microseconds"),// 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}// ...- Fractional numbers (to make
1/3*2*3accurate) - E notation, like 2E+10
- Unit types
- Timezones
- Binary/octal/decimal/hexadecimal/base32/base64
- Color codes
- Roman numerals
- Update
CHANGELOG.md - Bump the version number in
Cargo.toml - Run
cargo test - Create a git tag in format
v#.#.# - Add release notes to the generated GitHub release and publish it
- Run
cargo publish