PHP.ini设置精度= 14
342349.23 - 341765.07 = 584.15999999992 // floating point problem
PHP.ini设置,让我们说precision = 8
342349.23 - 341765.07 = 584.16 // voila!
演示:http://codepad.org/r7o086sS
这有多糟糕?
1.如果我只需要精确的2位数字计算(钱),我可以依靠这个解决方案吗?
2.如果没有,你能为我提供一个清楚的例子,当这个解决方案失败?
编辑:3.哪个PHP.ini.precision值适合最好的两位数,钱计算
>请注意,我不能使用整数计算(float * 100 = cents),这太晚了。
>我不打算工作在高于10 ^ 6的数字
>我不需要比较数字
更新
@Baba回答是好的,但他使用精度= 20,精度= 6在他的测试…所以,我仍然不知道是否会工作或不工作。
请考虑以下内容:
让我们说precision = 8,只有我做的是加法和减法 –
A B = C
A-B = C
问题1:0..999999.99之间的数字的精确解决方法会失败,其中A和B是带小数位数的数字?如果是这样,请给我一个例子。
简单的测试会做的工作:
// 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)."\n"; } }
but obviously 99999999 * 2
is too big job so I can’t run this test
问题2:如何估计/计算何时精确解决方法失败?没有这么疯狂的测试?有什么数学*,直接的答案吗?如何计算是要失败还是失败?
*我不需要知道浮点计算工作,但如果解决方法失败,如果你知道精度,范围A和B
浮点运算被许多人认为是一个深奥的主题。这是相当令人惊讶的,因为浮点在计算机系统中是普遍存在的。大多数分数不具有作为二进制分数的精确表示,因此存在一些四舍五入。一个好的开始是What Every Computer Scientist Should Know About Floating-Point Arithmetic
问题
问题1
Can I rely on this solution if I need just @H_502_61@precise 2 digits calculations (money)?
答案1
如果你需要精确的2位数,那么答案是否定的,你不能使用PHP精度设置来确定一个2位十进制的所有时间,即使你不打算工作的数字高于10 ^ 6。
在计算期间,如果长度小于8,则可能增加精度长度
问题2
If not can you provide me a clear example when this solutions fails?
答案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;
14.5824 <---- not precise 2 digits calculations even if precision is 8
问题3
Which PHP.ini.precision value suits best two digits,money calculations?
答案3
精确和金钱计算是两个不同的事情…它不是一个好主意,使用PHP精度作为您的财务计算或浮点长度的基础
简单测试
Lest使用bcmath,number_format和简单减号运行一些示例
基础
$a = 342349.23; $b = 341765.07;
实施例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,PHP_EOL;
584.15999999997438863 584.15999999999996817 <----- Round having a party 584.16 584.15 <-------- here is 15 because precision value is 20
实施例B
ini_set('precision',14); // change to 14 echo $a - $b,PHP_EOL;
584.15999999997 584.16 584.16 584.16 <-------- at 14 it changed to 16
实施例C.
ini_set('precision',6); // change to 6 echo $a - $b,PHP_EOL;
584.16 584.16 584.16 584.00 <--- at 6 it changed to 00
实施例D
ini_set('precision',3); // change to 3 echo $a - $b,PHP_EOL;
584 584 584.16 <-------------------------------- They only consistent value 0.00 <--- at 3 .. everything is gone
结论
忘记浮点,只计算在分,然后除以100,如果太晚只是简单地使用number_format它看起来一致的我。
更新
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
形式0到999999.99在0.01的增量是大约99,999,999的你的循环的组合可能性是9,800,000,000我真的不认为任何人都想为你运行这样的测试。
由于浮点是具有有限精度的二进制数,试图设置精度将具有有限的效果以确保精度这里是一个简单的测试:
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;
Total: 0.4 1.0408341E-17 <--- am sure you would expect 0.00 here ;
尝试
echo round($i,PHP_EOL; echo number_format($i,PHP_EOL;
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?
事实仍然是Floating Point有Accuracy Problems,但对于数学解决方案,你可以看看
> 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
不知道那个语句意味着什么