<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Igor Borodulin</title>
    <description>The latest articles on DEV Community by Igor Borodulin (@argen666).</description>
    <link>https://dev.to/argen666</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F912970%2Fc37ac0c1-8c3e-480f-8a45-25ae3808a619.jpg</url>
      <title>DEV Community: Igor Borodulin</title>
      <link>https://dev.to/argen666</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/argen666"/>
    <language>en</language>
    <item>
      <title>How to use BigDecimal in Java accurately</title>
      <dc:creator>Igor Borodulin</dc:creator>
      <pubDate>Sun, 21 Aug 2022 20:41:00 +0000</pubDate>
      <link>https://dev.to/argen666/how-to-use-bigdecimal-in-java-accurately-1ken</link>
      <guid>https://dev.to/argen666/how-to-use-bigdecimal-in-java-accurately-1ken</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--H_xfXL3y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8qeqm4w3k6wuh5io65yn.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--H_xfXL3y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8qeqm4w3k6wuh5io65yn.jpg" alt="Header" width="880" height="627"&gt;&lt;/a&gt;&lt;br&gt;
Want to know why float and double data types should never be used for floating-point calculations?&lt;br&gt;
Check out this quick overview to learn more about using BigDecimal to perform precise operations. &lt;/p&gt;
&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Most enterprise applications operate floating-point values.&lt;br&gt;&lt;br&gt;
Fintech, e-commerce, finance, and other applications deal with floating-point operations daily and need complete precision control for all calculations.&lt;br&gt;&lt;br&gt;
The developers need to know what data type of Java is appropriate for representing floating-point values, especially monetary values.&lt;br&gt;&lt;br&gt;
Let's try to figure it out.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why double is not accurate
&lt;/h2&gt;

&lt;p&gt;The first thing that comes to mind is to use float and double data types.&lt;br&gt;&lt;br&gt;
However, these data types are not recommended if precise values are required.&lt;br&gt;
The fact is that the float and double types are intended primarily for scientific and engineering calculations.&lt;br&gt;&lt;br&gt;
They implement binary floating-point arithmetic carefully designed to quickly obtain the correct approximation for a wide range of values.&lt;br&gt;&lt;br&gt;
Unfortunately, these types do not give accurate results and therefore are unsuitable for monetary calculations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;1.03&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 0.6100000000000001 &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To get a deeper understanding of how floating-point numbers are represented, take a look at &lt;a href="https://en.wikipedia.org/wiki/IEEE_754"&gt;IEEE Standard for Floating-Point Arithmetic&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does BigDecimal ensure accuracy
&lt;/h2&gt;

&lt;p&gt;Going back to the introduction, let us see how BigDecimal represents a number and how it guarantees precision.&lt;br&gt;&lt;br&gt;
Looking at the source code of BigDecimal, we can find that a BigDecimal is represented by a number by an unscaled value and a scale:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BigDecimal&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Comparable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;BigDecimal&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;BigInteger&lt;/span&gt; &lt;span class="n"&gt;intVal&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// unscaled value&lt;/span&gt;
  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// scale&lt;/span&gt;
  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kd"&gt;transient&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;intCompact&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The scale field represents the scale of BigDecimal.&lt;br&gt;&lt;br&gt;
The unscaled values use a slightly more complex representation.&lt;br&gt;&lt;br&gt;
When the unscaled value exceeds the threshold (the default is Long.MAX_VALUE), the intVal field is used to store the value, and the intCompact field is stored Long.MIN_VALUE, for indicating the significand information is only available from intVal.&lt;br&gt;&lt;br&gt;
Otherwise, the unscaled value is compactly stored in the long-type intCompact field for the subsequent computation, and the intVal is empty.&lt;/p&gt;

&lt;p&gt;BigDecimal also provides a scale method to return the scale of the BigDecimal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;scale&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The comment on that method gives a detailed description of how the scale value is used:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Returns the scale of this BigDecimal. If zero or positive, the scale is the number of digits to the right of the decimal point. If negative, the unscaled value of the number is multiplied by ten to the power of the negation of the scale. For example, a scale of -3 means the unscaled value is multiplied by 1000.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Going back to the example above, the number 0.61, which cannot be precisely represented by binary, can be represented using BigDecimal, with unscaled value 61 and scale 2.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to create BigDecimal properly
&lt;/h2&gt;

&lt;p&gt;Looking at BigDecimal's source code, we can figure out four significant constructors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;BigDecimal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;BigDecimal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; 
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;BigDecimal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;BigDecimal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The scale of the BigDecimal created by the above four constructors is different.&lt;br&gt;
&lt;code&gt;BigDecimal(int)&lt;/code&gt; and &lt;code&gt;BigDecimal(long)&lt;/code&gt; are more straightforward and take integer input parameters, so their scales are both 0.&lt;br&gt;&lt;br&gt;
&lt;code&gt;BigDecimal(double)&lt;/code&gt; and &lt;code&gt;BigDecimal(String)&lt;/code&gt; scales require more detailed consideration.&lt;/p&gt;
&lt;h3&gt;
  
  
  What is wrong with BigDecimal(double)
&lt;/h3&gt;

&lt;p&gt;BigDecimal provides a method to create BigDecimal from double, but it is not recommended because the results can be somewhat unpredictable.&lt;br&gt;
The BigDecimal created using the double value 0.61 is not exactly equal to 0.61 because 0.61 cannot be represented precisely as a finite length binary.&lt;br&gt;
The actual representation is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;BigDecimal&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BigDecimal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.61&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 0.60999999999999998667732370449812151491641998291015625&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thus, using BigDecimal(double), especially for calculations involving financial transactions, is extremely dangerous because it may lose precision.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creation using BigDecimal(String)
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;BigDecimal(String)&lt;/code&gt; constructor is completely predictable.&lt;br&gt;
The line &lt;code&gt;new BigDecimal("0.61")&lt;/code&gt; creates a BigDecimal, which is exactly equal to 0.61:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;BigDecimal&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BigDecimal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"0.61"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 0.61&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, it must be noted that the scales of &lt;code&gt;new BigDecimal("0.610000")&lt;/code&gt; and new &lt;code&gt;BigDecimal("0.61")&lt;/code&gt; are 6 and 2, respectively.&lt;br&gt;
The result of the equals method comparison of these BigDecimals is false.&lt;/p&gt;

&lt;p&gt;Accordingly, there are two following methods to create a BigDecimal that can accurately represent 0.61:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;BigDecimal&lt;/span&gt; &lt;span class="n"&gt;recommend1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BigDecimal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"0.61"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;BigDecimal&lt;/span&gt; &lt;span class="n"&gt;recommend2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BigDecimal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;valueOf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.61&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The method &lt;code&gt;BigDecimal.valueOf(double)&lt;/code&gt; uses two-step process and implemented by calling the &lt;code&gt;Double.toString(double)&lt;/code&gt; method.&lt;br&gt;
The first step is to convert the Double to String. The second step is to convert String to BigDecimal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;BigDecimal&lt;/span&gt; &lt;span class="nf"&gt;valueOf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;BigDecimal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Double&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Since computers use binary code to store and process data, many floating-point numbers cannot be represented exactly as a binary fraction of any finite length.&lt;br&gt;&lt;br&gt;
Therefore, a way of representing floating-point numbers in computers was adopted through approximations, such as single-precision floating-point and double-precision floating-point formats.&lt;br&gt;&lt;br&gt;
Unfortunately, these types do not give accurate results and are unsuitable for precise calculations, especially affecting financial transactions.&lt;br&gt;&lt;br&gt;
Accordingly, using &lt;code&gt;BigDecimal(double)&lt;/code&gt; is extremely dangerous because it may lose precision and unpredictable results.&lt;br&gt;&lt;br&gt;
Thus, the generally preferred and strongly recommended way to create BigDecimal is using a &lt;code&gt;BigDecimal(String)&lt;/code&gt; and &lt;code&gt;BigDecimal.valueOf(double)&lt;/code&gt; methods.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;[1] Link to the &lt;a href="https://en.wikipedia.org/wiki/IEEE_754"&gt;IEEE Standard for Floating-Point Arithmetic&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
