{"id":21206231,"url":"https://github.com/rtmigo/precise_kt","last_synced_at":"2026-05-20T03:35:53.654Z","repository":{"id":60877830,"uuid":"483411922","full_name":"rtmigo/precise_kt","owner":"rtmigo","description":"Kotlin/JVM compensated summation of Double sequences to calculate sum, mean, standard deviation","archived":false,"fork":false,"pushed_at":"2022-10-23T07:57:25.000Z","size":331,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-21T15:32:14.571Z","etag":null,"topics":["babuska","binary64","double","floating-point","jvm","kahan","kotlin","math","precision","stats"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","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-19T21:14:58.000Z","updated_at":"2022-04-20T03:23:00.000Z","dependencies_parsed_at":"2022-10-06T06:25:41.158Z","dependency_job_id":null,"html_url":"https://github.com/rtmigo/precise_kt","commit_stats":null,"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rtmigo%2Fprecise_kt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rtmigo%2Fprecise_kt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rtmigo%2Fprecise_kt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rtmigo%2Fprecise_kt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rtmigo","download_url":"https://codeload.github.com/rtmigo/precise_kt/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243658274,"owners_count":20326467,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["babuska","binary64","double","floating-point","jvm","kahan","kotlin","math","precision","stats"],"created_at":"2024-11-20T20:54:55.723Z","updated_at":"2026-05-20T03:35:48.607Z","avatar_url":"https://github.com/rtmigo.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"![Generic badge](https://img.shields.io/badge/JVM-8-blue.svg)\n[![Maven Central](https://img.shields.io/maven-central/v/io.github.rtmigo/precise.svg)](https://search.maven.org/artifact/io.github.rtmigo/precise)\n\n# [precise](https://github.com/rtmigo/precise_kt#readme)\n\nImplements [compensated summation](https://en.wikipedia.org/wiki/Kahan_summation_algorithm)\nfor sequences of `Double`. Reduces rounding errors associated with limited\nprecision of floating-point numbers.\n\n```kotlin\nval numbers = List(420) { 0.1 }  // 420 x 0.01\n\nnumbers.preciseSumOf { it } // 42.0 (compensated sum)\nnumbers.sumOf { it }        // 42.00000000000033 (naive sum)\n```\n\nThe table shows the total error when summing the same sequence of random\nnumbers. All the terms were rounded to 0.0001 before addition. In the **%**\ncolumn, the error of `preciseSumOf` compared to `sumOf`.\n\n| Terms     | err( sum )    | err( preciseSum ) | %      |\n|-----------|---------------|-------------------|--------|\n| 10        | 0.00000000003 | 0.00000000003     | 100.0% |\n| 100       | 0.0000000008  | 0.00000000002     | 3.03%  |\n| 1,000     | 0.000000001   | 0.0000000001      | 9.57%  |\n| 10,000    | 0.00000002    | 0.0000000007      | 3.57%  |\n| 100,000   | 0.0000005     | 0.000000004       | 0.77%  |\n| 1,000,000 | 0.000009      | 0.000000003       | 0.03%  |\n\n% is err(preciseSum) / err(sum)\n\nMost of the functions use \"second-order iterative Kahan–Babuška algorithm\"\nby [Klein (2005)](https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.582.288\u0026rep=rep1\u0026type=pdf)\n.\n\n# Install [![Maven Central](https://img.shields.io/maven-central/v/io.github.rtmigo/precise.svg)](https://search.maven.org/artifact/io.github.rtmigo/precise)\n\n```kotlin\n// build.gradle.kts\n\ndependencies {\n    implementation(\"io.github.rtmigo:precise: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/precise).\n\n\n# Lambda functions\n\n```kotlin\nval sequence = listOf(1, 2, 3)\n\n// sum\nsequence.preciseSumOf { it * 0.1 }  // equals 0.6\n\n// arithmetic mean\nsequence.preciseMeanOf { it * 0.1 }  // equals 0.2\n\n// standard deviation and mean\nval (stdev, mean) = sequence.preciseStdevMean { it * 0.1 }\n```\n\n# Running sum\n\nRunning sum, immutable version:\n\n```kotlin\nvar sum = PreciseSum(5.0)  // 5.0 is optional starting value\n\nsum += 0.1\nsum += listOf(0.2, 0.3)\nprintln(sum.value)  // 5.6\n\nsum -= 0.2\nprintln(sum.value)  // 5.4\n```\n\nRunning sum, mutable version (faster):\n\n```kotlin\nval sum = MutablePreciseSum(5.0)  // 5.0 is optional starting value\n\nsum.add(0.1)\nsum.add(listOf(0.2, 0.3))\nprintln(sum.value)  // 5.6\n\nsum.add(-0.2)\nprintln(sum.value)  // 5.4\n```\n\n# Benchmarks\n\nAn alternative to compensated summation is to use BigDecimal: there is no error\nwhen summing them. However, even in the case of a pre-generated array,\nBigDecimals are 5-10 times slower.\n\n| Type       | Method                                     | Kind    | Time    |\n|------------|--------------------------------------------|---------|---------|\n| Double     | `List\u003cDouble\u003e.sumOf`                       | naive   | 17 ms   |\n| Double     | `List\u003cDouble\u003e.preciseSumOf`                | precise | 48 ms   |\n| Double     | `MutablePreciseSum`                        | precise | 50 ms   |\n| Double     | `PreciseSum` (immutable)                   | precise | 75 ms   |\n| BigDecimal | `List\u003cBigDecimal\u003e.sumOf`                   | naive   | 501 ms  |\n| BigDecimal | `List\u003cDouble\u003e.sumOf { it.toBigDecimal() }` | naive   | 3192 ms |\n\n# Other functions\n\n`kahanSumOf` implements\nKahan [compensated summation algorithm](https://en.wikipedia.org/wiki/Kahan_summation_algorithm)\nin its traditional form. The accuracy is worse than `preciseSumOf`, but better\nthan the naive sum.\n\n```kotlin\nval sequence = listOf(1, 2, 3)\nsequence.kahanSumOf { it * 0.1 }  // 0.6\n```\n\n`cascadeSumOf`\nperforms [pairwise summation](https://en.wikipedia.org/wiki/Pairwise_summation).\nThe accuracy is worse than `preciseSumOf`, but better than the naive sum.\n\n```kotlin\nval sequence = listOf(1, 2, 3)\nsequence.cascadeSumOf { it * 0.1 }  // 0.6\n```\n\n`welfordMeanOf` calculates the arithmetic mean, avoiding overflow when summing\ntoo large values.\n\n```kotlin\nval sequence = listOf(1, 2, 3)\nprintln(sequence.welfordMeanOf { it * 0.1 })  // 0.3\n```\n\n## License\n\nCopyright © 2022 [Artsiom iG](https://github.com/rtmigo).\nReleased under the [MIT License](LICENSE).","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frtmigo%2Fprecise_kt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frtmigo%2Fprecise_kt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frtmigo%2Fprecise_kt/lists"}