{"id":50325094,"url":"https://github.com/dunnock/decimal64","last_synced_at":"2026-05-29T05:30:25.383Z","repository":{"id":360721732,"uuid":"1250388719","full_name":"dunnock/decimal64","owner":"dunnock","description":"Rust 64 bit fixed scale decimal based on underlying i64, supports parsing from float string repr","archived":false,"fork":false,"pushed_at":"2026-05-27T15:09:15.000Z","size":52,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-27T17:08:10.658Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dunnock.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-26T15:25:00.000Z","updated_at":"2026-05-27T15:09:33.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/dunnock/decimal64","commit_stats":null,"previous_names":["dunnock/decimal64"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/dunnock/decimal64","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dunnock%2Fdecimal64","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dunnock%2Fdecimal64/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dunnock%2Fdecimal64/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dunnock%2Fdecimal64/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dunnock","download_url":"https://codeload.github.com/dunnock/decimal64/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dunnock%2Fdecimal64/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33639050,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-29T02:00:06.066Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-05-29T05:30:24.567Z","updated_at":"2026-05-29T05:30:25.378Z","avatar_url":"https://github.com/dunnock.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# decimal64\n\n64-bit fixed-point decimal with compile-time scale, for Rust.\n\n[![Crates.io](https://img.shields.io/crates/v/decimal64.svg)](https://crates.io/crates/decimal64)\n[![docs.rs](https://img.shields.io/docsrs/decimal64)](https://docs.rs/decimal64)\n\n## Quick start\n\n```rust\nuse decimal64::Decimal64;\n\nfn main() -\u003e Result\u003c(), Box\u003cdyn std::error::Error\u003e\u003e {\n    let price: Decimal64\u003c4\u003e = \"123.4567\".parse()?;\n    let qty:   Decimal64\u003c4\u003e = \"10.0000\".parse()?;\n\n    // same-scale arithmetic\n    let total = price * qty;\n    println!(\"{}\", total);  // \"1234.5670\" (truncation in fractional component)\n\n    // rescale before mixing scales\n    let qty2: Decimal64\u003c2\u003e = \"10.00\".parse()?;\n    let total2 = price * qty2.rescale_into::\u003c4\u003e().unwrap();\n    println!(\"{}\", total2);  // \"1234.5670\"\n\n    Ok(())\n}\n```\n\n## Scale table\n\n`Decimal64\u003cS\u003e` stores the mathematical value as an `i64` whose unit is `10^(-S)`.\n\n| S  | Unit name    | Typical use                              | Max absolute value   |\n|----|--------------|------------------------------------------|----------------------|\n|  2 | centis       | USD cents, stock shares (round lots)     | ~92.2 quadrillion    |\n|  4 | basis points | FX rates, equity prices                  | ~922 trillion        |\n|  6 | micros       | Crypto prices, nanosecond timing         | ~9.22 trillion       |\n|  9 | nanos        | Gas prices (Ethereum), high-freq rates   | ~9.22 billion        |\n| 18 | attos        | Smallest Ethereum unit (wei)             | ~9.22                |\n\nThe scale `S` is enforced at compile time: `Decimal64\u003cA\u003e + Decimal64\u003cB\u003e` where `A ≠ B`\nis a **compile error**. Use `rescale_into` to align scales explicitly.\n\n`S \u003e 18` is rejected at compile time (would overflow `ONE = 10^S`).\n\n## Arithmetic rules\n\n### Addition and subtraction\n\nBoth operands must share the same scale `S` — enforced by the type system.\n\n```rust\nlet a: Decimal64\u003c4\u003e = \"1.2345\".parse().unwrap();\nlet b: Decimal64\u003c4\u003e = \"0.0001\".parse().unwrap();\nlet c = a + b;  // Decimal64\u003c4\u003e(\"1.2346\")\n```\n\nOverflow panics. Use `checked_add` / `saturating_add` for fallible or clamping variants.\n\n### Multiplication (same-scale)\n\n`a * b` computes `(a.raw() as i128 * b.raw() as i128) / 10^S` and returns a `Decimal64\u003cS\u003e`.\nThe intermediate `i128` prevents overflow for valid `i64` inputs. The fractional component\nof the product is **truncated toward zero** (keeping scale `S`, not `2S`).\n\nOverflow panics. Use `checked_mul` / `saturating_mul` for fallible or clamping variants.\n\n### Division\n\n`a / b` computes `(a.raw() * 10^S) / b.raw()` in `i128`, **truncating toward zero**.\nDivision by zero panics. Use `checked_div` or `div_round(rhs, mode)` for alternatives.\n\n### Checked and saturating variants\n\nAll operators have checked and saturating companions:\n\n```rust\na.checked_add(b)           // → Option\u003cDecimal64\u003cS\u003e\u003e\na.checked_sub(b)           // → Option\u003cDecimal64\u003cS\u003e\u003e\na.checked_mul(b)           // → Option\u003cDecimal64\u003cS\u003e\u003e\na.checked_div(b)           // → Option\u003cDecimal64\u003cS\u003e\u003e  (None for div-by-zero)\n\na.saturating_add(b)        // → Decimal64\u003cS\u003e  (clamps to MAX/MIN)\na.saturating_sub(b)        // → Decimal64\u003cS\u003e\na.saturating_mul(b)        // → Decimal64\u003cS\u003e\n\na.div_round(b, Round::NearestEven)          // panics on div-by-zero\na.checked_div_round(b, Round::TowardPosInf) // → Option\u003cDecimal64\u003cS\u003e\u003e\n```\n\n### Rescaling\n\n```rust\nlet d2: Decimal64\u003c2\u003e = \"1.25\".parse().unwrap();\nlet d4: Decimal64\u003c4\u003e = d2.rescale_into::\u003c4\u003e().unwrap();  // 1.2500 — exact, always succeeds\nlet d1: Decimal64\u003c1\u003e = d2.rescale_into::\u003c1\u003e();  // None — \"1.25\" has fractional digits lost\nlet d1r = d2.rescale_round_into::\u003c1\u003e(Round::Nearest).unwrap();  // 1.3\n```\n\n## Parsing\n\n`Decimal64\u003cS\u003e` implements `FromStr`. Extra fractional digits beyond `S` are silently\n**truncated toward zero**. Scientific notation and underscore separators are not supported.\n\n```rust\nlet d: Decimal64\u003c4\u003e = \"123.45678\".parse().unwrap();  // stores 123.4567 (truncated)\nlet d: Decimal64\u003c4\u003e = \".5\".parse().unwrap();         // 0.5000\nlet d: Decimal64\u003c4\u003e = \"5.\".parse().unwrap();         // 5.0000\n```\n\n## f64 conversions\n\n```rust\nlet d = Decimal64::\u003c4\u003e::from_f64(1.23456789);          // NearestEven rounding\nlet d = Decimal64::\u003c4\u003e::from_f64_round(x, Round::Nearest);\nlet f: f64 = d.to_f64();\n```\n\n`from_f64` clamps on overflow; `NaN` maps to `ZERO`. `to_f64` is lossless for\n`|raw| \u003c 2^53`; larger values lose precision inherent to `f64`.\n\n## Benchmark\n\nParse throughput vs. competitors at `Decimal64::\u003c4\u003e` on x86-64 Linux (stable Rust, optimised):\n\n| Input               | decimal64 (M/s) | f64 (M/s) | rust_decimal (M/s) | bigdecimal (M/s) |\n|---------------------|-----------------|-----------|---------------------|------------------|\n| `\"0\"`               | 214.6           | 157.2     | 102.0               | 37.1             |\n| `\"1.23\"`            | 191.2           | 130.9     | 90.6                | 20.9             |\n| `\"123.4567\"`        | 155.8           | 115.9     | 83.5                | 18.5             |\n| `\"9999999999.9999\"` | 118.2           | 113.5     | 73.8                | 15.9             |\n| `\"-0.000001\"`       | 166.6           | 115.2     | 79.5                | 18.3             |\n\nFull results and arithmetic benchmarks: [`docs/bench-results.md`](docs/bench-results.md).\n\n## System requirements\n\n- **Stable Rust** — MSRV: 1.65 (edition 2021, `f64::round_ties_even` since 1.77;\n  see Cargo.toml for exact MSRV)\n- No external C dependencies\n- `std` required (for `Display` and `Error`; `no_std` is a future cycle goal)\n\n## Design\n\nSee [`docs/design.md`](docs/design.md) for the full design rationale, arithmetic rules,\nparse algorithm, and const-generic limitations on stable Rust.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdunnock%2Fdecimal64","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdunnock%2Fdecimal64","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdunnock%2Fdecimal64/lists"}