{"id":21206241,"url":"https://github.com/rtmigo/dec_kt","last_synced_at":"2026-04-28T19:34:37.412Z","repository":{"id":61832448,"uuid":"481999599","full_name":"rtmigo/dec_kt","owner":"rtmigo","description":"Kotlin wrapper for Java BigDecimal","archived":false,"fork":false,"pushed_at":"2022-10-23T23:10:14.000Z","size":117,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-14T23:11:52.957Z","etag":null,"topics":["decimal","decimal-numbers","decimal64","dfp","floating-point","java","kotlin"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rtmigo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-04-15T15:20:51.000Z","updated_at":"2022-10-22T07:20:09.000Z","dependencies_parsed_at":"2023-01-20T09:26:04.588Z","dependency_job_id":null,"html_url":"https://github.com/rtmigo/dec_kt","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/rtmigo/dec_kt","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rtmigo%2Fdec_kt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rtmigo%2Fdec_kt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rtmigo%2Fdec_kt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rtmigo%2Fdec_kt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rtmigo","download_url":"https://codeload.github.com/rtmigo/dec_kt/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rtmigo%2Fdec_kt/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32396327,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-28T14:34:11.604Z","status":"ssl_error","status_checked_at":"2026-04-28T14:32:37.009Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["decimal","decimal-numbers","decimal64","dfp","floating-point","java","kotlin"],"created_at":"2024-11-20T20:54:58.139Z","updated_at":"2026-04-28T19:34:37.384Z","avatar_url":"https://github.com/rtmigo.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Maven Central](https://img.shields.io/maven-central/v/io.github.rtmigo/dec.svg)](https://search.maven.org/artifact/io.github.rtmigo/dec)\n![Generic badge](https://img.shields.io/badge/JVM-11-blue.svg)\n\n# [dec](https://github.com/rtmigo/dec_kt#readme)\n\n`Dec` object represents a 64-bit decimal floating-point number.\n\n- Unlike `Double`, `Dec` has no binary rounding artifacts.\n\n- Unlike `BigDecimal`, `Dec` has a\n  fixed [decimal64](https://en.wikipedia.org/wiki/Decimal64_floating-point_format)\n  precision.\n\nThese two qualities make `Dec` more predictable in arithmetic.\n\n`Dec` is a thin Kotlin wrapper for Java `BigDecimal`.\n\n## Install [![Maven Central](https://img.shields.io/maven-central/v/io.github.rtmigo/dec.svg)](https://search.maven.org/artifact/io.github.rtmigo/dec)\n\n```kotlin\n// build.gradle.kts\n\ndependencies {\n    implementation(\"io.github.rtmigo:dec:X.X.X\")\n    // replace X.X.X with actual version\n}\n```\n\nFind the latest version and instructions for other build systems\nat [Maven Central](https://search.maven.org/artifact/io.github.rtmigo/dec).\n\n## Basic use\n\n```kotlin\nimport io.github.rtmigo.dec.Dec\n\nfun main() {\n    val pi = Dec(\"3.14159265359\")\n    val r = Dec(5)\n\n    println(pi * (r * r))\n}\n```\n\n## Dec vs Double\n\n`Double` introduces rounding artifacts where you wouldn't expect them.\n\n```kotlin\n0.1 + 0.2  // = 0.30000000000000004\n```\n\nBecause of this rounding the same trivial operations with the same numbers, but\nin a different order, give different results.\n\n```kotlin\n(0.1 + 0.2) - (0.1 + 0.2)  // = 0.0\n0.1 + 0.2 - 0.1 - 0.2   // = 2.7755575615628914e-17\n```\n\n`Dec` behaves more predictably.\n\n```kotlin\nDec(0.1) + Dec(0.2)  // = 0.3\n\nDec(0.1) + Dec(0.2) - Dec(0.1) - Dec(0.2)  // = 0.0\n```\n\nIn fact, `Dec` also has a rounding problem. But this happens when you literally\noperate on 16-digit numbers like `2.718281828459045` and some inaccuracy in the\nlower digits is expected.\n\n\u003cdetails\u003e\n\u003csummary\u003eMore horrors of double arithmetic\u003c/summary\u003e\n\n\nLet's sum `0.1` multiple times and compare to the ideal result.\n\n```kotlin\nfun difference(summands: Int): Double {\n    val ideal = summands * 0.1\n    val sum = (1..summands).sumOf { 0.1 }\n    return sum - ideal\n}\n```\n\n| Summands      | Difference (plain)    | Difference (scientific) |\n|---------------|-----------------------|-------------------------|\n| 10            | -0.000000000000000111 | -1.1102230246251565E-16 |\n| 100           | -0.00000000000001954  | -1.9539925233402755E-14 |\n| 1,000         | -0.000000000001406875 | -1.4068746168049984E-12 |\n| 10,000        | 0.000000000158820512  | 1.588205122970976E-10   |\n| 100,000       | 0.0000000188483682    | 1.8848368199542165E-8   |\n| 1,000,000     | 0.000001332882675342  | 1.3328826753422618E-6   |\n| 10,000,000    | -0.00016102462541312  | -1.610246254131198E-4   |\n| 100,000,000   | -0.018870549276471138 | -0.018870549276471138   |\n| 1,000,000,000 | -1.2545821815729141   | -1.2545821815729141     |\n\n\u003c/details\u003e\n\n## Dec vs BigDecimal\n\n`BigDecimal` fixes oddities in `Double` rounding.\n\nBut the syntax for using BigDecimal in Java is far from intuitive. For example,\nhere is how we compute `125 / 100`:\n\n```kotlin\nBigDecimal(\"125\").divide(BigDecimal(\"100\"), MathContext.DECIMAL64)\n```\n\nKotlin standard library adds arithmetic operators to the `BigDecimal`, but\nthe result of the calculations can be surprising.\n\n```kotlin\nBigDecimal(\"125\") / BigDecimal(\"100\")      // = 1\nBigDecimal(\"125.0\") / BigDecimal(\"100.0\")  // = 1.2\nBigDecimal(\"125.00\") / BigDecimal(\"100\")   // = 1.25\n```\n\nCalculations with `Dec` are both intuitive and predictable.\n\n```kotlin\nDec(\"125\") / Dec(\"100\")      // = 1.25\nDec(\"125.0\") / Dec(\"100.0\")  // = 1.25\nDec(\"125.00\") / Dec(\"100\")   // = 1.25 \n```\n\n## Implicit conversions\n\nWhen the left side of an expression is a `Dec` instance, the right side can have\nbasic numeric types.\n\n```kotlin\nDec(\"125\") + 8  // = 133.0\n\nBigDecimal(\"125\") + 8  // does not compile in Kotlin \n```\n\n## Speed considerations\n\n### Dec is faster than rounding Double\n\n`Double` with its rounding artifacts is much faster than `Dec`. It's tempting\nto use `Double` and round it up after every calculation. However, properly done\nrounding can be much slower than just using `Dec`.\n\n```kotlin\nimport org.apache.commons.math3.util.Precision\nimport io.github.rtmigo.dec.*\n\nfun slowest(n: Int): Double {\n    var x: Double = 0.0\n    for (i in 1..n) {\n        x += 0.01\n        x = Precision.round(x, 2)  // slow!\n    }\n    return x\n}\n\nfun average(n: Int): Double {\n    var x = Dec(\"0.0\")\n    for (i in 1..n) {\n        x += Dec(\"0.01\")  // faster than Precision.round \n    }\n    return x.toDouble()\n}\n\nfun fastest(n: Int): Double {\n    var x: Double = 0.0\n    for (i in 1..n) {\n        x += 0.01\n        // we can reuse x if we are satisfied with  \n        // inaccurate decimal value on each step \n    }\n    // we also must be sure that the accumulated error \n    // is less than the rounding\n    return Precision.round(x, 2)\n}\n\nfun hyperspeed(n: Int) = Precision.round(n * 0.01, 2)  // ;)\n```\n\n### Reusing is faster than creation\n\n```kotlin\nval CONST_17 = Dec(17)\n\nfun faster(x: Dec) = x * CONST_17\n\nfun slower(x: Dec) = x + Dec(17)\nfun also_slower(x: Dec) = x + 17  // this creates Dec(17) anyway\n```\n\n### Multiplication is faster than division\n\n```kotlin\nDec(23) / Dec(100)   // slower\nDec(23) * Dec(0.01)  // faster\n```\n\n### Dec(string) is faster than Dec(double)\n\n```kotlin\nDec(\"1.23\")  // this is faster\nDec(1.23)  // will create intermediate string \"1.23\" anyway\n```\n\n`Double.toDecBin()` does not use intermediate string conversion, but be prepared\nthat:\n\n```kotlin\n100.0.toDecBin() - 0.1.toDecBin()  // = 99.90000000000001\n```\n\n# License\n\nCopyright © 2022 [Artsiom iG](https://github.com/rtmigo).\nReleased under the [ISC License](LICENSE).","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frtmigo%2Fdec_kt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frtmigo%2Fdec_kt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frtmigo%2Fdec_kt/lists"}