mirror of
https://github.com/foomo/foomo-docs.git
synced 2025-10-16 12:35:40 +00:00
62 lines
13 KiB
HTML
62 lines
13 KiB
HTML
<!doctype html>
|
|
<html lang="en" dir="ltr" class="blog-wrapper blog-post-page plugin-blog plugin-id-default" data-has-hydrated="false">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="generator" content="Docusaurus v3.0.0">
|
|
<title data-rh="true">Accuracy of decimal computations | foomo project docs</title><meta data-rh="true" name="viewport" content="width=device-width,initial-scale=1"><meta data-rh="true" name="twitter:card" content="summary_large_image"><meta data-rh="true" property="og:url" content="https://www.foomo.org/blog/accuracy-of-decimal-computations"><meta data-rh="true" property="og:locale" content="en"><meta data-rh="true" name="docusaurus_locale" content="en"><meta data-rh="true" name="docusaurus_tag" content="default"><meta data-rh="true" name="docsearch:language" content="en"><meta data-rh="true" name="docsearch:docusaurus_tag" content="default"><meta data-rh="true" property="og:title" content="Accuracy of decimal computations | foomo project docs"><meta data-rh="true" name="description" content="Intro"><meta data-rh="true" property="og:description" content="Intro"><meta data-rh="true" property="og:type" content="article"><meta data-rh="true" property="article:published_time" content="2023-03-06T00:00:00.000Z"><meta data-rh="true" property="article:author" content="https://github.com/uebriges,https://github.com/marusicbostjan"><meta data-rh="true" property="article:tag" content="golang,currency,decimal accuracy"><link data-rh="true" rel="icon" href="/img/favicon.ico"><link data-rh="true" rel="canonical" href="https://www.foomo.org/blog/accuracy-of-decimal-computations"><link data-rh="true" rel="alternate" href="https://www.foomo.org/blog/accuracy-of-decimal-computations" hreflang="en"><link data-rh="true" rel="alternate" href="https://www.foomo.org/blog/accuracy-of-decimal-computations" hreflang="x-default"><link data-rh="true" rel="preconnect" href="https://SUATUVZDDM-dsn.algolia.net" crossorigin="anonymous"><link rel="alternate" type="application/rss+xml" href="/blog/rss.xml" title="foomo project docs RSS Feed">
|
|
<link rel="alternate" type="application/atom+xml" href="/blog/atom.xml" title="foomo project docs Atom Feed">
|
|
|
|
|
|
|
|
<link rel="search" type="application/opensearchdescription+xml" title="foomo project docs" href="/opensearch.xml"><link rel="stylesheet" href="/assets/css/styles.78fe5ce6.css">
|
|
<script src="/assets/js/runtime~main.638e5c2c.js" defer="defer"></script>
|
|
<script src="/assets/js/main.1248442c.js" defer="defer"></script>
|
|
</head>
|
|
<body class="navigation-with-keyboard">
|
|
<script>!function(){function t(t){document.documentElement.setAttribute("data-theme",t)}var e=function(){try{return new URLSearchParams(window.location.search).get("docusaurus-theme")}catch(t){}}()||function(){try{return localStorage.getItem("theme")}catch(t){}}();t(null!==e?e:"light")}(),function(){try{const c=new URLSearchParams(window.location.search).entries();for(var[t,e]of c)if(t.startsWith("docusaurus-data-")){var a=t.replace("docusaurus-data-","data-");document.documentElement.setAttribute(a,e)}}catch(t){}}()</script><div id="__docusaurus"><div role="region" aria-label="Skip to main content"><a class="skipToContent_fXgn" href="#__docusaurus_skipToContent_fallback">Skip to main content</a></div><nav aria-label="Main" class="navbar navbar--fixed-top"><div class="navbar__inner"><div class="navbar__items"><button aria-label="Toggle navigation bar" aria-expanded="false" class="navbar__toggle clean-btn" type="button"><svg width="30" height="30" viewBox="0 0 30 30" aria-hidden="true"><path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" d="M4 7h22M4 15h22M4 23h22"></path></svg></button><a class="navbar__brand" href="/"><b class="navbar__title text--truncate">foomo</b></a><a class="navbar__item navbar__link" href="/docs/general">General</a><a class="navbar__item navbar__link" href="/docs/frontend">Frontend</a><a class="navbar__item navbar__link" href="/docs/backend">Backend</a><a class="navbar__item navbar__link" href="/docs/devops">DevOps</a><a class="navbar__item navbar__link" href="/docs/projects">Projects</a></div><div class="navbar__items navbar__items--right"><a aria-current="page" class="navbar__item navbar__link navbar__link--active" href="/blog">Blog</a><div class="navbarSearchContainer_Bca1"><button type="button" class="DocSearch DocSearch-Button" aria-label="Search"><span class="DocSearch-Button-Container"><svg width="20" height="20" class="DocSearch-Search-Icon" viewBox="0 0 20 20"><path d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z" stroke="currentColor" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round"></path></svg><span class="DocSearch-Button-Placeholder">Search</span></span><span class="DocSearch-Button-Keys"></span></button></div></div></div><div role="presentation" class="navbar-sidebar__backdrop"></div></nav><div id="__docusaurus_skipToContent_fallback" class="main-wrapper mainWrapper_z2l0"><div class="container margin-vert--lg"><div class="row"><aside class="col col--3"><nav class="sidebar_re4s thin-scrollbar" aria-label="Blog recent posts navigation"><div class="sidebarItemTitle_pO2u margin-bottom--md">Recent posts</div><ul class="sidebarItemList_Yudw clean-list"><li class="sidebarItem__DBe"><a class="sidebarItemLink_mo7H" href="/blog/go-race-conditions-testing-and-coverage">Go race conditions testing and coverage</a></li><li class="sidebarItem__DBe"><a aria-current="page" class="sidebarItemLink_mo7H sidebarItemLinkActive_I1ZP" href="/blog/accuracy-of-decimal-computations">Accuracy of decimal computations</a></li><li class="sidebarItem__DBe"><a class="sidebarItemLink_mo7H" href="/blog/why-bundle-size-is-important">Why bundle size is important?</a></li><li class="sidebarItem__DBe"><a class="sidebarItemLink_mo7H" href="/blog/prometheus-cardinality-issues">Prometheus Is Out Of Memory. Again.</a></li><li class="sidebarItem__DBe"><a class="sidebarItemLink_mo7H" href="/blog/searching-for-search-engines">The never ending search a search engine 2022-01 edition</a></li></ul></nav></aside><main class="col col--7" itemscope="" itemtype="https://schema.org/Blog"><article itemprop="blogPost" itemscope="" itemtype="https://schema.org/BlogPosting"><meta itemprop="description" content="Intro"><header><h1 class="title_f1Hy" itemprop="headline">Accuracy of decimal computations</h1><div class="container_mt6G margin-vert--md"><time datetime="2023-03-06T00:00:00.000Z" itemprop="datePublished">March 6, 2023</time></div><div class="margin-top--md margin-bottom--sm row"><div class="col col--6 authorCol_Hf19"><div class="avatar margin-bottom--sm"><a href="https://github.com/uebriges" target="_blank" rel="noopener noreferrer" class="avatar__photo-link"><img class="avatar__photo" src="https://github.com/uebriges.png" alt="Patrick Buchner" itemprop="image"></a><div class="avatar__intro" itemprop="author" itemscope="" itemtype="https://schema.org/Person"><div class="avatar__name"><a href="https://github.com/uebriges" target="_blank" rel="noopener noreferrer" itemprop="url"><span itemprop="name">Patrick Buchner</span></a></div><small class="avatar__subtitle" itemprop="description">MSc</small></div></div></div><div class="col col--6 authorCol_Hf19"><div class="avatar margin-bottom--sm"><a href="https://github.com/marusicbostjan" target="_blank" rel="noopener noreferrer" class="avatar__photo-link"><img class="avatar__photo" src="https://github.com/marusicbostjan.png" alt="Boštjan Marušič" itemprop="image"></a><div class="avatar__intro" itemprop="author" itemscope="" itemtype="https://schema.org/Person"><div class="avatar__name"><a href="https://github.com/marusicbostjan" target="_blank" rel="noopener noreferrer" itemprop="url"><span itemprop="name">Boštjan Marušič</span></a></div><small class="avatar__subtitle" itemprop="description">PhD</small></div></div></div></div></header><div id="__blog-post-container" class="markdown" itemprop="articleBody"><h2 id="intro">Intro</h2>
|
|
<p>Calculating with money can be tricky if not taken proper precautions. Some might be tempted to use float representation for calculating with currency values. That is problematic because of possible rounding errors.</p>
|
|
<h2 id="finite-accuracy-of-representation">Finite accuracy of representation</h2>
|
|
<p>Floating points are represented like this</p>
|
|
<p><img alt="Floating point representation" src="/assets/images/floating_point_representation-efc73a8c1b722a82b772c2cd7ee7ba99.webp" width="810" height="226"></p>
|
|
<p>Not every number can be represented with a finite number of decimal places</p>
|
|
<p>0.01 —> 0.0000011001100110011…</p>
|
|
<p>Taking 17 places of the above results in 0.010000000000000001</p>
|
|
<p>Consider the following code snipet that shows the missing accuracy</p>
|
|
<pre><code class="language-go">func main() {
|
|
|
|
var n float64 = 0
|
|
|
|
for i := 0; i < 1000; i++ {
|
|
n += .01
|
|
}
|
|
|
|
fmt.Println(n)
|
|
|
|
}
|
|
</code></pre>
|
|
<p>Result: 9.999999999999831</p>
|
|
<h2 id="money-computations">Money computations</h2>
|
|
<p>They can't be done with floating-point as it would inevitably lead to rounding errors.</p>
|
|
<p>Even the following packages are problematic:</p>
|
|
<p><a href="https://github.com/shopspring/decimal">github.com/shopspring/decimal</a></p>
|
|
<p><a href="https://github.com/Rhymond/go-money">github.com/Rhymond/go-money</a></p>
|
|
<pre><code class="language-go">a := decimal.NewFromInt(2)
|
|
b := decimal.NewFromFloat(300.99)
|
|
c := a.Mul(b)
|
|
d := c.Div(decimal.NewFromInt(3))
|
|
</code></pre>
|
|
<h2 id="solution">Solution</h2>
|
|
<p>Use Int by representing money in cents:</p>
|
|
<ul>
|
|
<li>10.99 -> 1099 (cents)</li>
|
|
<li>10.9900 -> 109900 (4 digit tax)</li>
|
|
</ul>
|
|
<h2 id="conclusion">Conclusion</h2>
|
|
<p><strong>Division is a problem!</strong></p>
|
|
<p>1/3 - > 0.33333333…
|
|
Correct way: 0.33, 0.33, 0.34</p>
|
|
<p>When doing money calculations one should avoid division as it inevitably leads to loss of accuracy.
|
|
When dividing make sure to round to cent and deal with diffs.</p>
|
|
<p>Division by 10^k is ok as long as we are inside of the range of the data type.</p></div><footer class="row docusaurus-mt-lg blogPostFooterDetailsFull_mRVl"><div class="col"><b>Tags:</b><ul class="tags_jXut padding--none margin-left--sm"><li class="tag_QGVx"><a class="tag_zVej tagRegular_sFm0" href="/blog/tags/golang">golang</a></li><li class="tag_QGVx"><a class="tag_zVej tagRegular_sFm0" href="/blog/tags/currency">currency</a></li><li class="tag_QGVx"><a class="tag_zVej tagRegular_sFm0" href="/blog/tags/decimal-accuracy">decimal accuracy</a></li></ul></div><div class="col margin-top--sm"><a href="https://github.com/foomo/foomo-docs/tree/main/foomo/blog/2023-03-06-accuracy-of-decimal-computations/index.mdx" target="_blank" rel="noopener noreferrer" class="theme-edit-this-page"><svg fill="currentColor" height="20" width="20" viewBox="0 0 40 40" class="iconEdit_Z9Sw" aria-hidden="true"><g><path d="m34.5 11.7l-3 3.1-6.3-6.3 3.1-3q0.5-0.5 1.2-0.5t1.1 0.5l3.9 3.9q0.5 0.4 0.5 1.1t-0.5 1.2z m-29.5 17.1l18.4-18.5 6.3 6.3-18.4 18.4h-6.3v-6.2z"></path></g></svg>Edit this page</a></div></footer></article><nav class="pagination-nav docusaurus-mt-lg" aria-label="Blog post page navigation"><a class="pagination-nav__link pagination-nav__link--prev" href="/blog/go-race-conditions-testing-and-coverage"><div class="pagination-nav__sublabel">Newer Post</div><div class="pagination-nav__label">Go race conditions testing and coverage</div></a><a class="pagination-nav__link pagination-nav__link--next" href="/blog/why-bundle-size-is-important"><div class="pagination-nav__sublabel">Older Post</div><div class="pagination-nav__label">Why bundle size is important?</div></a></nav></main><div class="col col--2"><div class="tableOfContents_bqdL thin-scrollbar"><ul class="table-of-contents table-of-contents__left-border"><li><a href="#intro" class="table-of-contents__link toc-highlight">Intro</a></li><li><a href="#finite-accuracy-of-representation" class="table-of-contents__link toc-highlight">Finite accuracy of representation</a></li><li><a href="#money-computations" class="table-of-contents__link toc-highlight">Money computations</a></li><li><a href="#solution" class="table-of-contents__link toc-highlight">Solution</a></li><li><a href="#conclusion" class="table-of-contents__link toc-highlight">Conclusion</a></li></ul></div></div></div></div></div><footer class="footer"><div class="container container-fluid"><div class="row footer__links"><div class="col footer__col"><div class="footer__title">github</div><ul class="footer__items clean-list"><li class="footer__item"><a href="https://github.com/foomo" target="_blank" rel="noopener noreferrer" class="footer__link-item">https://github.com/foomo</a></li></ul></div><div class="col footer__col"><div class="footer__title">legal</div><ul class="footer__items clean-list"><li class="footer__item"><a class="footer__link-item" href="/etc/imprint">Imprint</a></li></ul></div></div><div class="footer__bottom text--center"><div class="footer__copyright">© 2024 bestbytes</div></div></div></footer></div>
|
|
</body>
|
|
</html> |