gpt4 book ai didi

php - 我可以依靠 PHP php.ini 精度解决浮点问题吗

转载 作者:IT王子 更新时间:2023-10-29 01:16:06 25 4
gpt4 key购买 nike

我已经为 floating point problem 找到了一些解决方法在 PHP 中:

php.ini 设置 precision = 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 回答很好,但他在测试中使用了 precision=20precision=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 的范围,当解决方法失败时


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

最佳答案

简介

许多人认为浮点运算是一门深奥的学科。这是相当令人惊讶的,因为 float 在计算机系统中无处不在。大多数小数没有二进制小数的精确表示,因此会进行一些舍入。一个好的开始是 What Every Computer Scientist Should Know About Floating-Point Arithmetic

问题

问题一

Can I rely on this solution if I need just 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 使用 bcmathnumber_format 和简单的 minus 一起运行一些示例

基础

$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, 2), 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;
echo floatval(round($a - $b, 2)), PHP_EOL;
echo number_format($a - $b, 2), PHP_EOL;
echo bcsub($a, $b, 2), 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;
echo floatval(round($a - $b, 2)), PHP_EOL;
echo number_format($a - $b, 2), PHP_EOL;
echo bcsub($a, $b, 2), 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;
echo floatval(round($a - $b, 2)), PHP_EOL;
echo number_format($a - $b, 2), PHP_EOL;
echo bcsub($a, $b, 2), PHP_EOL;

输出

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

结论

忘掉 float ,只计算 cents 然后除以 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

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

由于 float 是精度有限的二进制数,因此尝试设置 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 "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,2) , PHP_EOL;
echo number_format($i,2) , 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 PointAccuracy 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

enter image description here

不确定那句话是什么意思:)

关于php - 我可以依靠 PHP php.ini 精度解决浮点问题吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14587290/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com