6

我已阅读有关在 PHP 中使用浮点类型的浮点指南。答案是使用 BC Math 扩展。使用字符串可以将浮点数表示为精确类型并防止浮点数和整数问题。

同时,我在 Github 和这个网站上没有找到任何使用 BC 数学扩展的好例子。什么是强制 PHP 使用字符串的干净方法,如何评估它们?

特别是使用 MySQL DECIMAL 数据类型的 BC 数学扩展的最佳方法是什么?

我使用 PHP 5.4.10 进行的示例测试,正确答案是:0.2999999999996

<?php
bcscale(13);

$a = '0.3';
$b = '0.0000000000004';

echo $a-$b; // 0.3
echo '<br />';
echo bcsub($a, $b); // 0.2999999999996
echo '<hr />';

$a = "0.3";
$b = "0.0000000000004";

echo $a-$b; // 0.3
echo '<br />';
echo bcsub($a, $b); // 0.2999999999996
echo '<hr />';

$a = 0.3;
$b = 0.0000000000004;

echo $a-$b; // 0.3
echo '<br />';
echo bcsub($a, $b); // 0.3000000000000
echo '<hr />';

$a = '0.3';
$b = '0.0000000000004' + 0;

echo $a-$b; // 0.3
echo '<br />';
echo bcsub($a, $b); // 0.3000000000000
echo '<hr />';

$a = (string) 0.3;
$b = (string) 0.0000000000004;

echo $a-$b; // 0.3
echo '<br />';
echo bcsub($a, $b); // 0.3000000000000
echo '<hr />';

$a = strval(0.3);
$b = strval(0.0000000000004);

echo $a-$b; // 0.3
echo '<br />';
echo bcsub($a, $b); // 0.3000000000000
?>
4

1 回答 1

4

最好的方法不是使用 BC Math,而是开始使用 GMP。看看benchmark。GMP 比 BC Math 快 30 倍。

我使用 DECIMAL(12, 0) AND DECIMAL(27,0) 并且 php start 很糟糕 apr。在 10^19 或更大。演示:

//PHP Version 5.3.10,  FreeBSD 8.2-RELEASE amd64

$a = pow(10, 18);
var_dump($a, $a > ($a - 1), ($a - 1) > $a, ($a - 1) == $a, ($a - 1) === $a);
// int(1000000000000000000)
// bool(true)
// bool(false)
// bool(false)
// bool(false)

$a = pow(10, 19);
var_dump($a, $a > ($a - 1), ($a - 1) > $a, ($a - 1) == $a, ($a - 1) === $a);

// double(1.0E+19)
// bool(false)
// bool(false)
// bool(true)
// bool(true)

我做了Decimal课,这里是简单的实现。稍后您可以使用本机 php 数学运算或 BC 数学或任何您想要的实现相同的接口。是的,函数调用和对象创建会有开销,但我们编写的代码其他开发人员可以阅读,不是吗?

来自PHP Secure Communications的PS Guys有他们自己的实现 - Math_BigInteger,它涵盖了所有潜在需求,但对我的任务来说太重了。

更新:由于 PHP 5.6 GMP 实现了内部运算符重载,因此 gmp 资源可以用作常规数字(大部分)。

于 2013-04-16T12:47:35.860 回答