【问题标题】:Subtraction calculation for the same variables differs in different situations相同变量的减法计算在不同情况下有所不同
【发布时间】:2017-03-20 11:56:30
【问题描述】:

问题有点严重。我需要的输出是2.9558577807620168e-12

1#working.php

 <?php 
     $a = 465.90928248188;
     $b = 15.651243716447;
     $c = 450.25803876543; 

     echo $a - $b -$c // output 2.9558577807620168e-12 as expected
 ?>

2#notworking.php

<?php 

     lot of arithmetic calculation almost 200-250 LoC
     $array1_28x1[3]; // 465.90928248188
     $array2_28x1[3]; // 15.651243716447
     $array3_28x1[3]; // 450.25803876543

     echo $array1_28x1[3] - $array2_28x1[3] - $array3_28x1[3];
     // output -4.5474735088646E-13

 ?>

我不明白是什么问题。会不会是内存泄漏?我也进行了逐步调试,但找不到任何解决方案。而且这是非常重要的计算,所以不能忽略。

注意:在这 250 LoC 下,变量的值没有变化。我在减法之前已经转储了变量。

【问题讨论】:

  • 你是不是故意在 echo 行中写了array2_... 两次?上面的信息说array3_...
  • 你能var_dump($array1_28x1[3])和其他2个变量
  • 计算取决于类型。每种类型都有不同的精度。您正在将其推向极限,浮动范围在 1E2 和 1E-13 之间。这是 10 的 16 步。请参阅:php.net/manual/en/language.types.float.php“虽然它取决于系统,但 PHP 通常使用 IEEE 754 双精度格式,由于按 1.11e-16 的顺序舍入,这将给出最大的相对误差。”
  • @KIKOSoftware 我很难称达到最大相对错误“将其推到极限”的千分之一。
  • @ccKep:你错了,计算还涉及到百位数字……越过零点。

标签: php math subtraction


【解决方案1】:

您确实使用了 2 次 array2,所以我认为这是一个错字。 当我执行此代码时,它可以工作:

<?php 

     $array1_28x1[3] = 465.90928248188;
     $array2_28x1[3] = 15.651243716447;
     $array3_28x1[3] = 450.25803876543;

     echo $array1_28x1[3] - $array2_28x1[3] - $array3_28x1[3];
     // output 2.955857780762E-12

【讨论】:

  • 但是你注意到如果他真的执行了显示的代码,结果不会像评论中指出的那样接近于零?
  • @Ricardo 是的。它适用于简单的场景,但是当我使用相同类型和值的相同计算时,我得到不同的结果,而我提到的长时间计算
  • 你能做一个数组的 var_dump 吗?
  • 是的,我已经做到了,它显示了与浮点数据类型相同的值。
【解决方案2】:

问题出现了,因为您显示的中间变量只有 14 个有效数字。这隐藏了原始计算中存在但在重建中缺失的 2 个附加数字。

一般的解决方案是认识到在浮点算术的范围内,您实际上计算了零。

要获得可重构的结果,您可以将中间结果转换为显示的字符串,然后将其转换回数字。这将为您提供可以从显示的中间结果中重现的结果。

对于本质上是浮点噪声并因此表示零的结果,您的输入比例/大小为 1000,这给出了绝对误差比例。 1e4*1e-16=1e-12 的浮点噪声规模。两个指示的结果都在这个范围内,即都必须被认为是零。

【讨论】:

  • 我们可以猜测我们想要的一切,在所有 PHP 版本中使用相同的值 gives the correct/expected output - 所以我不认为 OP 正在使用他认为他正在使用的变量或那些 200-250 LOC 改变那些OP 没有预料到的变量。
  • 不,问题中的问题是使用四舍五入的值作为输入会给您带来与使用原始值不同的结果。之前 250 行的计算使用了具有额外未知 2.5 位的变量,而这些变量会产生重大影响。
  • 这应该属于“或者那些 200-250 LOC 将这些变量更改为 OP 不期望的东西”。 - 如果他发布的那些数字恰好是回声之前的数字,那么这应该不是问题。
  • 是的,但同样,OP 的问题在于,显示 14 位数字的双精度数不会是“确切的数字”。
  • @LutzL 如果我正确理解你的答案,你的意思是我应该使用 16 位小数而不是 14 位,对吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-24
相关资源
最近更新 更多