【问题标题】:bcadding very small floats gives 0bcadding 非常小的浮点数给出 0
【发布时间】:2013-01-31 02:34:44
【问题描述】:

感谢堆栈,我了解了浮点不精度,所以我转到了 bc 函数。

这在“普通”浮点数上效果很好,但对于非常小的浮点数,比如10^-10 类型,bcadd 总是给出0

谁能告诉我我做错了什么才能使这些小浮点数精确地相加?

提前非常感谢!


PHP

$numerator = 1;
$denominator = 1000000000;
$quotientOne = $numerator / $denominator;

$numerator = 1;
$denominator = 1000000000000000;
$quotientTwo = $numerator / $denominator;

$smallSum = bcadd($quotientOne, $quotientTwo, 100);

echo $quotientOne . "<br>";
echo $quotientTwo . "<br>";
echo $smallSum . "<br>";

给予

1.0E-9
1.0E-15
0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

【问题讨论】:

标签: php floating-point-precision bc


【解决方案1】:

The / operator 返回浮点数或整数。它干扰了您正确使用 bcadd() 的尝试。在 bcadd() 有机会展示它的东西之前,浮点算术的局限性就会出现。

echo gettype($numerator / $denominator);
double

请改用bcdiv()。请注意,bc*() 函数将字符串作为参数,并且它们也返回一个字符串。

$ cat code/php/test.php
<?php
$num_1 = 1;
$denom_1 = 1000000000;

# Cast values to string type to be crystal clear about what you're doing.
$q_1 = bcdiv((string)$num_1, (string)$denom_1, strlen($denom_1));
printf("q_1: %s\n", $q_1);

$num_2 = 1;
$denom_2 = 1000000000000000;

# php will do an implicit conversion to string anyway, though.
$q_2 = bcdiv($num_2, $denom_2, strlen($denom_2));
printf("q_2: %s\n", $q_2);

printf("sum: %s\n", bcadd($q_1, $q_2, strlen($denom_2)));
?>

$ php code/php/test.php
q_1: 0.0000000010
q_2: 0.0000000000000010
sum: 0.0000000010000010

任意精度算术本质上比浮点算术慢。这就是您为获得数十、数百或数千位精度所付出的代价。

【讨论】:

  • 是的,这将比类似的浮点运算花费更长的时间。但是浮点运算返回错误的答案,不是吗?您可以通过各种方式将值转换或转换为字符串,但 php 通常会为您进行隐式转换。 (参见上面的代码和 cmets。)关键是在进行任意精度算术时避免使用浮点表达式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多