[READ-ONLY] Mirror of https://github.com/probablykasper/cpc. Text calculator with support for units and conversion cpc.kasper.space
calculator cli conversion converter library math package units units-converter wasm website
0

Configure Feed

Select the types of activity you want to include in your feed.

242 2 26

Clone this repository

https://tangled.org/kasper.space/cpc https://tangled.org/did:plc:3zz4fru6e6zzv6dz4zbf2l7h
git@tangled.org:kasper.space/cpc git@tangled.org:did:plc:3zz4fru6e6zzv6dz4zbf2l7h

For self-hosted knots, clone URLs may differ based on your setup.



README.md

cpc#

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.

Crates.io Documentation

List of all supported units

Web Interface#

Try it out at cpc.kasper.space

CLI Installation#

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.

CLI Usage#

cpc '2h/3 to min'

Examples#

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

Supported unit types#

  • Normal numbers
  • Time
  • Length
  • Area
  • Volume
  • Mass
  • Digital storage (bytes etc)
  • Energy
  • Power
  • Electric current
  • Resistance
  • Voltage
  • Pressure
  • Frequency
  • Speed
  • Temperature

API Installation#

Add cpc as a dependency in Cargo.toml.

API Usage#

use cpc::eval;
use cpc::units::Unit;

match eval("3m + 1cm", true, false) {
    Ok(answer) => {
        // answer: Number { value: 301, unit: Unit::Centimeter }
        println!("Evaluated value: {} {:?}", answer.value, answer.unit)
    },
    Err(e) => {
        println!("{e}")
    }
}

Accuracy#

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.

Dev Instructions#

Get started#

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

Adding a unit#

Nice resources for adding units:

1. Add the unit#

In src/units.rs, units are specified like this:

pub enum UnitType {
  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.

2. Add a test for the unit#

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.

3. Add the unit to the lexer#

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
}
// ...

Potential Improvements#

Releasing a new version#

  1. Update CHANGELOG.md
  2. Bump the version number in Cargo.toml
  3. Run cargo test
  4. Create a git tag in format v#.#.#
  5. Add release notes to the generated GitHub release and publish it
  6. Run cargo publish