Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <h1>Introduction</h1> <p>Floating-point arithmetic is considered an esoteric subject by many people. This is rather surprising because floating-point is ubiquitous in computer systems. Most fractional numbers don't have an exact representation as a binary fraction, so there is some rounding going on. A good start is <a href="http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html" rel="noreferrer">What Every Computer Scientist Should Know About Floating-Point Arithmetic</a></p> <h2>Questions</h2> <h3>Question 1</h3> <blockquote> <p>Can I rely on this solution if I need just <strong>precise 2 digits calculations</strong> (money)?</p> </blockquote> <h3>Answer 1</h3> <p>If you need need <strong>precise 2 digits</strong> then the answer is <strong>NO</strong> you can not use the php precision settings to ascertain a <strong>2 digit</strong> decimal all the time even if you are <code>not going to work on numbers higher than 10^6</code>. </p> <p>During calculations there is possibility that the precision length can be increased if the length is less than 8</p> <h3>Question 2</h3> <blockquote> <p>If not can you provide me a clear example when this solutions fails?</p> </blockquote> <h3>Answer 2</h3> <pre><code>ini_set('precision', 8); // your precision $a = 5.88 ; // cost of 1kg $q = 2.49 ;// User buys 2.49 kg $b = $a * 0.01 ; // 10% Discount only on first kg ; echo ($a * $q) - $b; </code></pre> <p>Output </p> <pre><code>14.5824 &lt;---- not precise 2 digits calculations even if precision is 8 </code></pre> <h3>Question 3</h3> <blockquote> <p>Which php.ini.precision value suits best two digits, money calculations?</p> </blockquote> <h3>Answer 3</h3> <p>Precision and Money calculation are 2 different things ... it's not a good idea to use PHP precision for as a base for your financial calculations or floating point length </p> <h2>Simple Test</h2> <p>Lest Run some example together using <code>bcmath</code> , <code>number_format</code> and simple <code>minus</code></p> <p><strong><code>Base</code></strong> </p> <pre><code>$a = 342349.23; $b = 341765.07; </code></pre> <p><strong><code>Example A</code></strong></p> <pre><code>ini_set('precision', 20); // set to 20 echo $a - $b, PHP_EOL; echo floatval(round($a - $b, 2)), PHP_EOL; echo number_format($a - $b, 2), PHP_EOL; echo bcsub($a, $b, 2), PHP_EOL; </code></pre> <p>Output </p> <pre><code>584.15999999997438863 584.15999999999996817 &lt;----- Round having a party 584.16 584.15 &lt;-------- here is 15 because precision value is 20 </code></pre> <p><strong><code>Example B</code></strong></p> <pre><code>ini_set('precision', 14); // change to 14 echo $a - $b, PHP_EOL; echo floatval(round($a - $b, 2)), PHP_EOL; echo number_format($a - $b, 2), PHP_EOL; echo bcsub($a, $b, 2), PHP_EOL; </code></pre> <p>Output </p> <pre><code>584.15999999997 584.16 584.16 584.16 &lt;-------- at 14 it changed to 16 </code></pre> <p><strong><code>Example C</code></strong></p> <pre><code>ini_set('precision', 6); // change to 6 echo $a - $b, PHP_EOL; echo floatval(round($a - $b, 2)), PHP_EOL; echo number_format($a - $b, 2), PHP_EOL; echo bcsub($a, $b, 2), PHP_EOL; </code></pre> <p>Output </p> <pre><code>584.16 584.16 584.16 584.00 &lt;--- at 6 it changed to 00 </code></pre> <p><strong><code>Example D</code></strong></p> <pre><code>ini_set('precision', 3); // change to 3 echo $a - $b, PHP_EOL; echo floatval(round($a - $b, 2)), PHP_EOL; echo number_format($a - $b, 2), PHP_EOL; echo bcsub($a, $b, 2), PHP_EOL; </code></pre> <p>Output </p> <pre><code>584 584 584.16 &lt;-------------------------------- They only consistent value 0.00  &lt;--- at 3 .. everything is gone </code></pre> <h2>Conclusion</h2> <p>Forget about floating point and just calculate in <code>cents</code> then later divided by <code>100</code> if that is too late just simply use <code>number_format</code> it looks consistent to me .</p> <h1>Update</h1> <blockquote> <p>Question 1: Is precision workaround gonna fail for numbers between 0..999999.99, where A and B is a number with decimal places? If so please provide me an example</p> </blockquote> <p>Form <code>0</code> to <code>999999.99</code> at increment of of <code>0.01</code> is about <code>99,999,999</code> the combination possibility of your loop is <code>9,999,999,800,000,000</code> I really don't think anyone would want to run such test for you.</p> <p>Since floating point are binary numbers with finite precision trying to set <code>precision</code> would have limited effect to ensure accuracy Here is a simple test :</p> <pre><code>ini_set('precision', 8); $a = 0.19; $b = 0.16; $c = 0.01; $d = 0.01; $e = 0.01; $f = 0.01; $g = 0.01; $h = $a + $b + $c + $d + $e + $f + $g; echo "Total: " , $h , PHP_EOL; $i = $h-$a; $i = $i-$b; $i = $i-$c; $i = $i-$d; $i = $i-$e; $i = $i-$f; $i = $i-$g; echo $i , PHP_EOL; </code></pre> <p>Output </p> <pre><code>Total: 0.4 1.0408341E-17 &lt;--- am sure you would expect 0.00 here ; </code></pre> <p>Try </p> <pre><code>echo round($i,2) , PHP_EOL; echo number_format($i,2) , PHP_EOL; </code></pre> <p>Output </p> <pre><code>0 0.00 &lt;------ still confirms number_format is most accurate to maintain 2 digit </code></pre> <blockquote> <p>Question 2: How to estimate/calculate when precision workaround fails? Without such crazy tests? Is there any mathematical*, straight answer for it? How to calculate is gonna to fail or not?</p> </blockquote> <p>The fact sill remains <a href="http://en.wikipedia.org/wiki/Floating_point" rel="noreferrer">Floating Point</a> have <a href="http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems" rel="noreferrer">Accuracy Problems</a> but for mathematical solutions you can look at</p> <ul> <li><a href="http://en.wikipedia.org/wiki/Floating_point#Machine_precision_and_backward_error_analysis" rel="noreferrer">Machine precision and backward error analysis</a></li> <li><a href="http://en.wikipedia.org/wiki/Floating_point#Minimizing_the_effect_of_accuracy_problems" rel="noreferrer">Minimizing the effect of accuracy problems</a></li> </ul> <blockquote> <p>i don't need to know floating point calculations works, but when workaround fails if you know precision, and range of A and B</p> </blockquote> <p><img src="https://upload.wikimedia.org/math/a/3/0/a302c220e330c52c50dbedeb7ff8859b.png" alt="enter image description here"></p> <p>Not sure what that statement means :)</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

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