当前位置: 首页 > 面试题库 >

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

令狐弘益
2023-03-14
问题内容

我发现了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!

那有多糟?

1.如果我只需要精确的2位数字(货币),我可以依靠此解决方案吗?

2.如果解决方案失败了,您能否为我提供一个清晰的例子?

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

  • 请注意,我不能使用整数计算(float * 100 =美分),这样做太迟了。
  • 我不会处理高于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";
  }
}

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

问题2: 当精度解决方法失败时,如何估算/计算?没有如此疯狂的考验? 是否有任何数学*的直接答案? 如何计算是否会失败?

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

请记住, 我真的知道 美分和bcmath是最好的解决方案。但是我仍然不确定解决方法是否会因减法和加法而失败或失败


问题答案:

介绍

浮点算术被许多人视为深奥的话题。这是相当令人惊讶的,因为浮点数在计算机系统中无处不在。大多数小数没有精确表示为二进制分数,因此会进行一些舍入。一个好的开始是每位计算机科学家都应该了解的浮点运算法则

问题

问题1

如果我只需要 精确的2位数字 (货币),我可以依靠此解决方案吗?

答案1

如果您需要 精确的2位数字, 那么答案是 否定的, 即使您一直使用php精度设置也无法始终确定 2位 小数not going towork on numbers higher than 10^6

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

问题2

如果不能,当此解决方案失败时,您能否提供清晰的示例?

答案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

哪个php.ini.precision值最适合两位数字和金钱计算?

答案3

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

简单测试

为了避免运行一些例子使用起来bcmathnumber_format并简单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;

输出量

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;

输出量

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;

输出量

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;

输出量

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

结论

忘掉浮点数,cents然后算入,然后除以100是否太晚,只要简单地使用number_format它就对我来说是一致的。

更新资料

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

0999999.99递增的形式0.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 "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


 类似资料:
  • 本文向大家介绍Java中浮点数精度问题的解决方法,包括了Java中浮点数精度问题的解决方法的使用技巧和注意事项,需要的朋友参考一下 问题描述 在项目中用Java做浮点数计算时,发现对于4.015*100这样的计算,结果不是预料中的401.5,而是401.49999999999994。如此长的位数,对于显示来说很不友好。 问题原因:浮点数表示 查阅相关资料,发现原因是:计算机中的浮点数并不能完全精确

  • 问题内容: 我该如何克服Java android中双精度乘法的精度问题?请注意,我正在将字符串值转换为double值。 例如:当我将两个double值相乘时: 我得到以下结果:0.8999999999999999 我得到的一些结果是。 0.6 * 3 = 1.7999999999999998; 0.2 * 0.2 = 0.04000000000000001; 等等 除了上述结果外,我想得到以下结果

  • 问题内容: 似乎减法正在引发某种问题,并且结果值是错误的。 78.75 = 787.5 * 10.0 / 100d 708.75 = 787.5-78.75 877.8499999999999 = 1586.6-708.75 最终的期望值为877.85。 应该怎么做才能确保计算正确? 问题答案: 要控制浮点算术的精度,应使用java.math.BigDecimal。阅读John Zukowski的

  • 我们已经探索了 Python 语言中的许多部分,现在我们将通过设计并编写一款程序来了解如何把这些部分组合到一起。这些程序一定是能做到一些有用的事情。这其中的方法就是去学习如何靠你自己来编写一份 Python 脚本。 问题 我们希望解决的问题如下: 我想要一款程序来备份我所有的重要文件。 虽然这是一个简单的问题,但是其中并没有足够的信息有助于让我们开始规划一份解决方案。我们需要进行一些分析(Anal

  • 不太会使用 Env 工具的请先看一遍 《Env 用户手册》(不长的,看完费不了几分钟) 提示 Env 工具和 源码 所处的目录都不能有中文或空格请先检查!! code 是一个命令 点 ‘.’ 是一个参数表示当前目录,中间有一个空格。 romfs ramfs 文件系统中的文件名和c的变量的命名一样,只能由英文字母开头且仅包含数字和下划线。 修改 qemu.bat 里面的参数时,要注意那是一行参数中间

  • 解决等级保护中主机安全和应用安全的合规问题 保证重大会议活动期间重要网站的正常运行 为网站及服务器的基础防护、安全监测、风险预警、应急处置提供重要手段