<?xml version="1.0" encoding="utf-8" standalone="yes"?><feed xmlns="http://www.w3.org/2005/Atom"><title>Bigdecimal</title><id>https://polgrabia.me/tags/bigdecimal/</id><updated>2025-03-12T00:20:58+02:00</updated><link rel="self" href="https://polgrabia.me/tags/bigdecimal/"/><link rel="alternate" type="text/html" href="https://polgrabia.me/tags/bigdecimal/"/><author><name>Tomasz Półgrabia</name></author><generator>Hugo</generator><entry><title>BigDecimal - why do we need it?</title><id>https://polgrabia.me/posts/20250312-bigdecimal-why-do-we-need/</id><link rel="alternate" href="https://polgrabia.me/posts/20250312-bigdecimal-why-do-we-need/"/><published>2025-03-12T00:20:58+02:00</published><updated>2025-03-12T00:20:58+02:00</updated><category term="java"/><category term="bigdecimal"/><content type="html">&lt;h2 id="why-do-we-need-it"&gt;Why do we need it?&lt;/h2&gt;
&lt;p&gt;This question is the pretty standard one in algorithmic interview questions. So, why do we need it? I think it&amp;rsquo;s fair to ask.
The main reason behind this is knowing how floating point numbers are being stored. Usually, you don&amp;rsquo;t need it to use
this knowledge otherwise to know &amp;ldquo;solution&amp;rdquo; but it&amp;rsquo;s good to know.&lt;/p&gt;
&lt;p&gt;The main reason is the precision or rather, the lack of it. In environments where we need to have big numbers very precise like
face values and when it&amp;rsquo;s multiplied by exchange ratios, the potential difference can be very signifcant. Therefore potential
financial risk can be signifcant, too.&lt;/p&gt;
&lt;p&gt;The standard double (or even more float) is stored with 8 bytes, the standard float consumes 4 bytes. However, it doesn&amp;rsquo;t
explain yet the reason why. Let&amp;rsquo;s take look it.&lt;/p&gt;
&lt;h2 id="root-causes"&gt;Root causes&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Double-precision_floating-point_format"&gt;Floating point precision&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s take a look how typical double looks like.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sign bit (most significant, the left one)&lt;/li&gt;
&lt;li&gt;Exponent (11 bits)&lt;/li&gt;
&lt;li&gt;Significand precision (mantissa) (53 bits, 52 stored).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, we see that the formula for our double number is as it follows:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;sign * mantissa * exponent
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;{1,1} * &amp;lt;1,2) * (2**exp)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;where both mantissa and exponent are stored binary wise.&lt;/p&gt;
&lt;p&gt;Knowing this, we see the formula for granularity is (2 ** (-11)) * (2 ** exponent) where the first part comes from mantissa precision
(smallest difference in mantissa). When it&amp;rsquo;s applied to exponent (in binary representation), we see the granularity will be decreasing
for the smaller numbers and increasing for the bigger numbers.&lt;/p&gt;
&lt;p&gt;For the big numbers like millions, especially when it&amp;rsquo;s a result of more complex formulas containing more factors and especially division
(it&amp;rsquo;s advised to divide numbers as late as it&amp;rsquo;s possible), the potential error caused by granularity and representation errors can
be really signifcant.&lt;/p&gt;
&lt;h2 id="how-bigdecimal-are-different"&gt;How BigDecimal are different?&lt;/h2&gt;
&lt;p&gt;BigDecimals don&amp;rsquo;t have the same limits as stndard floating point types. They are being stored &amp;lsquo;digit-wise&amp;rsquo;, digit by digit and they potentially
have unlimited number of digits allowed to be stored in BigDecimal (mantissa part) stored as BigIntiger under the hood
(decimal wise&amp;hellip; in the simplest implementation. Real implementation dealing with &amp;ldquo;compact&amp;rdquo; and &amp;ldquo;non-compact&amp;rdquo; case you can check
in the github source code of openjdk).&lt;/p&gt;
&lt;p&gt;However, they still cannot hold rational numbers like ( 2 / 3 ) and thus they cannot have &amp;ldquo;infinite&amp;rdquo; number representation of rational number.
Therefore, you need to be very careful when you divide and preferably perform it at the very end of computations.&lt;/p&gt;
&lt;p&gt;Be careful with representing dividing like 1 / 3 * 3 != 1 in computer world&amp;hellip; (1 / 3 cannot be stored precisely in binary stored mantissa)&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;The point is - just use BigDecimal when you suspect that you may need big numbers with good precision.&lt;/p&gt;</content></entry></feed>