6

PHP での float 型の使用に関するFloating-Point ガイドを読みました。答えは、BC Math 拡張機能を使用することです。文字列を使用すると、float を正確な型として表すことができ、float と整数の問題を防ぐことができます。

一方、Github とこのサイトで BC math 拡張機能を使用している良い例は見つかりませんでした。PHPに文字列の使用を強制するクリーンな方法は何ですか?それらを評価する方法は?

特に、MySQL DECIMAL データ型で BC Math 拡張機能を使用する最良の方法は何ですか?

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 を使用することです。ベンチマークを見てください。GMP は、BC Math よりも最大 30 倍高速です。

私は DECIMAL(12, 0) AND DECIMAL(27,0) を使用し、php start suck 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 に答える