• <bdo id='43C3R'></bdo><ul id='43C3R'></ul>
  1. <i id='43C3R'><tr id='43C3R'><dt id='43C3R'><q id='43C3R'><span id='43C3R'><b id='43C3R'><form id='43C3R'><ins id='43C3R'></ins><ul id='43C3R'></ul><sub id='43C3R'></sub></form><legend id='43C3R'></legend><bdo id='43C3R'><pre id='43C3R'><center id='43C3R'></center></pre></bdo></b><th id='43C3R'></th></span></q></dt></tr></i><div id='43C3R'><tfoot id='43C3R'></tfoot><dl id='43C3R'><fieldset id='43C3R'></fieldset></dl></div>
    <legend id='43C3R'><style id='43C3R'><dir id='43C3R'><q id='43C3R'></q></dir></style></legend>

  2. <tfoot id='43C3R'></tfoot>

    <small id='43C3R'></small><noframes id='43C3R'>

    1. 我可以依靠 PHP php.ini 精度解决方法来解决浮点问题吗

      时间:2023-10-31
        <bdo id='5QeVw'></bdo><ul id='5QeVw'></ul>
        <tfoot id='5QeVw'></tfoot>
            <i id='5QeVw'><tr id='5QeVw'><dt id='5QeVw'><q id='5QeVw'><span id='5QeVw'><b id='5QeVw'><form id='5QeVw'><ins id='5QeVw'></ins><ul id='5QeVw'></ul><sub id='5QeVw'></sub></form><legend id='5QeVw'></legend><bdo id='5QeVw'><pre id='5QeVw'><center id='5QeVw'></center></pre></bdo></b><th id='5QeVw'></th></span></q></dt></tr></i><div id='5QeVw'><tfoot id='5QeVw'></tfoot><dl id='5QeVw'><fieldset id='5QeVw'></fieldset></dl></div>

                <tbody id='5QeVw'></tbody>

            1. <legend id='5QeVw'><style id='5QeVw'><dir id='5QeVw'><q id='5QeVw'></q></dir></style></legend>

              • <small id='5QeVw'></small><noframes id='5QeVw'>

                本文介绍了我可以依靠 PHP php.ini 精度解决方法来解决浮点问题吗的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

                问题描述

                我在 PHP 中找到了一些 浮点问题的解决方法:

                php.ini 设置 precision = 14

                342349.23 - 341765.07 = 584.15999999992//浮点问题

                php.ini 设置,比如说 precision = 8

                342349.23 - 341765.07 = 584.16//瞧!

                演示:http://codepad.org/r7o086sS

                这有多糟糕?

                1.如果我只需要精确的 2 位数计算(钱),我可以依靠这个解决方案吗?

                <强>2.如果不能,当这个解决方案失败时,你能给我一个明确的例子吗?

                3. 哪个 php.ini.precision 值最适合两位数,金钱计算

                <小时>
                • 请注意,我不能使用整数计算(float*100 = cents),太晚了.
                • 我不会处理大于 10^6 的数字
                • 我不需要比较数字

                更新

                @Baba 的答案很好,但他在测试中使用了 precision=20, precision=6...所以我仍然不确定它是否会起作用或不是.

                请考虑以下事项:

                假设 precision = 8 而我唯一要做的就是加法 + 和减法 -

                A + B = C

                A - B = C

                问题 1: 对于 0..999999.99 之间的数字(其中 A 和 B 是带小数位的数字),精确解决方法会失败吗?如果是这样,请给我一个例子.

                简单的测试就可以了:

                //如果失败了,如果我使用 9,10,11 怎么办???//**失败时如何查找???**ini_set('精度', 8);for($a=0;$a<999999.99;$a+=0.01) {for($b=0;$b<999999.99;$b+=0.01) {//请注意我不需要测试比较 (round($a-$b,2) == ($a-$b))echo ($a + $b).','.($a - $b)." vs ";echo round($a + $b, 2).','.round($a - $b, 2)."
                ";}}

                但显然 99999999 * 2 工作量太大,所以我无法运行本次测试

                问题 2: 精确变通方法失败时如何估计/计算?没有如此疯狂的测试?有没有数学*的直接答案?如何计算会失败?

                *我不需要知道浮点计算是否有效,但是如果您知道精度以及 A 和 B 的范围,解决方法失败时

                <小时>

                请注意我真的知道 cents 和 bcmath 是最好的解决方案.但我仍然不确定减法和加法的解决方法是否会失败

                解决方案

                简介

                浮点运算被许多人认为是一门深奥的学科.这是相当令人惊讶的,因为浮点在计算机系统中无处不在.大多数小数没有作为二进制分数的精确表示,因此需要进行一些舍入.一个好的开始是每个计算机科学家都应该知道的关于浮点运算的知识

                问题

                问题 1

                <块引用>

                如果我只需要精确的 2 位数计算(钱),我可以依靠这个解决方案吗?

                回答 1

                如果您需要精确的 2 位,那么答案是 NO 您不能使用 php 精度设置来确定 2 位 小数即使您不打算处理高于 10^6 的数字,也始终如此.

                在计算过程中,如果长度小于8,有可能增加精度长度

                问题 2

                <块引用>

                如果不能,当这个解决方案失败时,你能提供一个明确的例子吗?

                回答 2

                ini_set('precision', 8);//你的精度$a = 5.88 ;//1公斤的成本$q = 2.49 ;//用户购买 2.49 公斤$b = $a * 0.01 ;//10% 折扣仅在第一公斤;回声 ($a * $q) - $b;

                输出

                14.5824 <---- 不精确的 2 位计算,即使精度为 8

                问题 3

                <块引用>

                哪个 php.ini.precision 值最适合两位数,货币计算?

                答案 3

                精度和金钱计算是两件不同的事情......使用 PHP 精度作为财务计算或浮点长度的基础并不是一个好主意

                简单测试

                避免使用 bcmathnumber_format 和简单的 minus

                一起运行一些示例

                基础

                $a = 342349.23;$b = 341765.07;

                示例A

                ini_set('precision', 20);//设置为20回声 $a - $b, PHP_EOL;echo floatval(round($a - $b, 2)), PHP_EOL;echo number_format($a - $b, 2), PHP_EOL;回声 bcsub($a, $b, 2), PHP_EOL;

                输出

                584.15999999997438863584.15999999999996817 <----- 开派对584.16584.15 <-------- 这里是 15 因为精度值是 20

                示例 B

                ini_set('precision', 14);//改为 14回声 $a - $b, PHP_EOL;echo floatval(round($a - $b, 2)), PHP_EOL;echo number_format($a - $b, 2), PHP_EOL;回声 bcsub($a, $b, 2), PHP_EOL;

                输出

                584.15999999997584.16584.16584.16 <-------- 在 14 变为 16

                示例 C

                ini_set('precision', 6);//改为 6回声 $a - $b, PHP_EOL;echo floatval(round($a - $b, 2)), PHP_EOL;echo number_format($a - $b, 2), PHP_EOL;回声 bcsub($a, $b, 2), PHP_EOL;

                输出

                584.16584.16584.16584.00 <--- 在 6 变为 00

                示例 D

                ini_set('precision', 3);//改为 3回声 $a - $b, PHP_EOL;echo floatval(round($a - $b, 2)), PHP_EOL;echo number_format($a - $b, 2), PHP_EOL;回声 bcsub($a, $b, 2), PHP_EOL;

                输出

                584584584.16 <-------------------------------- 他们只有一致的值0.00 <--- 在 3 .. 一切都消失了

                结论

                忘记浮点数,只计算 cents 然后除以 100 如果为时已晚,只需简单地使用 number_format 它看起来一致对我来说.

                更新

                <块引用>

                问题 1:对于 0..999999.99 之间的数字(其中 A 和 B 是带小数位的数字),精确解决方法会失败吗?如果是这样,请给我一个例子

                Form 0999999.990.01 为增量大约是 99,999,999 循环的组合可能性是9,999,999,800,000,000 我真的认为没有人愿意为你运行这样的测试.

                由于浮点数是具有有限精度的二进制数,因此尝试设置 precision 对确保准确性的效果有限这是一个简单的测试:

                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 "总计:" , $h , PHP_EOL;$i = $h-$a;$i = $i-$b;$i = $i-$c;$i = $i-$d;$i = $i-$e;$i = $i-$f;$i = $i-$g;回声 $i , PHP_EOL;

                输出

                总计:0.41.0408341E-17 <--- 我相信你会在这里期望 0.00 ;

                试试

                echo round($i,2) , PHP_EOL;echo number_format($i,2) , PHP_EOL;

                输出

                <代码>00.00 <-------- 仍然确认 number_format 最准确地保持 2 位数

                <块引用>

                问题 2:当精确解决方法失败时如何估计/计算?没有如此疯狂的测试?有没有数学*的直接答案?如何计算会不会失败?

                事实仍然是 浮点 有 精度问题,但您可以查看数学解决方案

                • 机器精度和后向误差分析
                • 最小化准确性问题的影响
                <块引用>

                我不需要知道浮点计算是否有效,但是如果您知道精度以及 A 和 B 的范围,当变通方法失败时

                不知道那句话是什么意思:)

                I've found some workaround for floating point problem in PHP:

                php.ini setting precision = 14

                342349.23 - 341765.07 = 584.15999999992 // floating point problem
                

                php.ini setting, let's say precision = 8

                342349.23 - 341765.07 = 584.16 // voila!
                

                Demo: http://codepad.org/r7o086sS

                How bad is that?

                1. Can I rely on this solution if I need just precise 2 digits calculations (money)?

                2. If not can you provide me a clear example when this solutions fails?

                Edit: 3. Which php.ini.precision value suits best two digits, money calculations


                • Please mind I can't use integer calculations (float*100 = cents), it's far too late for that.
                • I am not going to work on numbers higher than 10^6
                • I don't need to compare numbers

                UPDATE

                @Baba answer is good, but he used precision=20, precision=6 in his tests... So still i am not sure is it gonna work or not.

                Please consider following:

                Let's say precision = 8 and only thing I do is addition + and subtraction -

                A + B = C

                A - B = C

                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.

                Simple test would do the job:

                // if it fails what if I use 9,10,11 ???
                // **how to find when it fails??? **
                ini_set('precision', 8); 
                for($a=0;$a<999999.99;$a+=0.01) {
                  for($b=0;$b<999999.99;$b+=0.01) {
                     // mind I don't need to test comparision (round($a-$b,2) == ($a-$b))
                     echo ($a + $b).','.($a - $b)." vs ";
                     echo round($a + $b, 2).','.round($a - $b, 2)."
                ";
                  }
                }
                

                but obviously 99999999 * 2 is too big job so I can't run this test

                Question 2: How to estimate/calculate when precision workaround fails? Without such crazy tests? Is there any mathematicial*, straight answer for it? How to calculate is gonna to fail or not?

                *i don't need to know floating point calculations works, but when workaround fails if you know precision, and range of A and B


                Please mind I really know cents and bcmath are best solution. But still I am not sure is workaround gonna fails or not for substraction and addition

                解决方案

                Introduction

                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 What Every Computer Scientist Should Know About Floating-Point Arithmetic

                Questions

                Question 1

                Can I rely on this solution if I need just precise 2 digits calculations (money)?

                Answer 1

                If you need need precise 2 digits then the answer is NO you can not use the php precision settings to ascertain a 2 digit decimal all the time even if you are not going to work on numbers higher than 10^6.

                During calculations there is possibility that the precision length can be increased if the length is less than 8

                Question 2

                If not can you provide me a clear example when this solutions fails?

                Answer 2

                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;
                

                Output

                14.5824 <---- not precise 2 digits calculations even if precision is 8
                

                Question 3

                Which php.ini.precision value suits best two digits, money calculations?

                Answer 3

                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

                Simple Test

                Lest Run some example together using bcmath , number_format and simple minus

                Base

                $a = 342349.23;
                $b = 341765.07;
                

                Example A

                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;
                

                Output

                584.15999999997438863
                584.15999999999996817    <----- Round having a party 
                584.16
                584.15  <-------- here is 15 because precision value is 20
                

                Example B

                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;
                

                Output

                584.15999999997
                584.16
                584.16
                584.16  <-------- at 14 it changed to 16
                

                Example C

                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;
                

                Output

                584.16
                584.16
                584.16
                584.00  <--- at 6 it changed to 00 
                

                Example D

                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;
                

                Output

                584
                584
                584.16   <-------------------------------- They only consistent value 
                0.00 <--- at 3 .. everything is gone 
                

                Conclusion

                Forget about floating point and just calculate in cents then later divided by 100 if that is too late just simply use number_format it looks consistent to me .

                Update

                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

                Form 0 to 999999.99 at increment of of 0.01 is about 99,999,999 the combination possibility of your loop is 9,999,999,800,000,000 I really don't think anyone would want to run such test for you.

                Since floating point are binary numbers with finite precision trying to set precision would have limited effect to ensure accuracy Here is a simple test :

                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;
                

                Output

                Total: 0.4
                1.0408341E-17     <--- am sure you would expect 0.00 here ;
                

                Try

                echo round($i,2) , PHP_EOL;
                echo number_format($i,2) , PHP_EOL;
                

                Output

                0
                0.00    <------ still confirms number_format is most accurate to maintain 2 digit 
                

                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?

                The fact sill remains Floating Point have Accuracy Problems but for mathematical solutions you can look at

                • Machine precision and backward error analysis
                • Minimizing the effect of accuracy problems

                i don't need to know floating point calculations works, but when workaround fails if you know precision, and range of A and B

                Not sure what that statement means :)

                这篇关于我可以依靠 PHP php.ini 精度解决方法来解决浮点问题吗的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

                上一篇:使用phpunit在抽象类中模拟具体方法 下一篇:显示不带科学计数法的浮点值

                相关文章

                <i id='W5Csv'><tr id='W5Csv'><dt id='W5Csv'><q id='W5Csv'><span id='W5Csv'><b id='W5Csv'><form id='W5Csv'><ins id='W5Csv'></ins><ul id='W5Csv'></ul><sub id='W5Csv'></sub></form><legend id='W5Csv'></legend><bdo id='W5Csv'><pre id='W5Csv'><center id='W5Csv'></center></pre></bdo></b><th id='W5Csv'></th></span></q></dt></tr></i><div id='W5Csv'><tfoot id='W5Csv'></tfoot><dl id='W5Csv'><fieldset id='W5Csv'></fieldset></dl></div>

                  1. <legend id='W5Csv'><style id='W5Csv'><dir id='W5Csv'><q id='W5Csv'></q></dir></style></legend>

                    <tfoot id='W5Csv'></tfoot>
                    • <bdo id='W5Csv'></bdo><ul id='W5Csv'></ul>

                    <small id='W5Csv'></small><noframes id='W5Csv'>