Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>There are two common pitfalls when working with floating point arithmetic.</p> <p><strong>The first problem</strong> is that Ruby floating points have fixed precision. In practice this will either be 1) no problem for you or 2) disastrous, or 3) something in between. Consider the following:</p> <pre><code># float 1.0e+25 - 9999999999999999900000000.0 #=&gt; 0.0 # bigdecimal BigDecimal("1.0e+25") - BigDecimal("9999999999999999900000000.0") #=&gt; 100000000 </code></pre> <p>A precision difference of 100 million! Pretty serious, right?</p> <p>Except the precision error is only about 0.000000000000001% of the original number. It really is up to you to decide if this is a problem or not. But the problem is removed by using <code>BigDecimal</code> because it has arbitrary precision. Your only limit is memory available to Ruby.</p> <p><strong>The second problem</strong> is that floating points cannot express all fractions accurately. In particular, they have problems with <em>decimal</em> fractions, because floats in Ruby (and most other languages) are <em>binary</em> floating points. For example, the decimal fraction <code>0.2</code> is an eternally-repeating binary fraction (<code>0.001100110011...</code>). This can never be stored accurately in a binary floating point, no matter what the precision is.</p> <p>This can make a big difference when you're rounding numbers. Consider:</p> <pre><code># float (0.29 * 50).round #=&gt; 14 # not correct # bigdecimal (BigDecimal("0.29") * 50).round #=&gt; 15 # correct </code></pre> <p>A <code>BigDecimal</code> can describe <em>decimal</em> fractions precisely. However, there are fractions that cannot be described precisely with a decimal fraction either. For example <code>1/9</code> is an eternally-repeating decimal fraction (<code>0.1111111111111...</code>). </p> <p>Again, this will bite you when you round a number. Consider:</p> <pre><code># bigdecimal (BigDecimal("1") / 9 * 9 / 2).round #=&gt; 0 # not correct </code></pre> <p>In this case, using decimal floating points will <strong>still</strong> give a rounding error.</p> <p>Some conclusions:</p> <ul> <li>Decimal floats are awesome if you do calculations with decimal fractions (money, for example).</li> <li>Ruby's <code>BigDecimal</code> also works well if you need arbitrary precision floating points, and don't really care if they are decimal or binary floating points.</li> <li>If you work with (scientific) data, you're typically dealing with fixed precision numbers; Ruby's built-in floats will probably suffice.</li> <li>You can never expect arithmetic with <em>any</em> kind of floating point to be precise in all situations.</li> </ul>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload