PHP
BC数学(バイナリ計算機)
サーチ…
前書き
バイナリ電卓を使用して、2147483647-1までの任意のサイズと精度の数値を文字列形式で計算することができます。バイナリ電卓は、PHPの浮動小数点計算よりも正確です。
構文
- 文字列bcadd(文字列$ left_operand、文字列$ right_operand [、int $ scale = 0])
- int bccomp(文字列$ left_operand、文字列$ right_operand [、int $ scale = 0])
- string bcdiv(文字列$ left_operand、文字列$ right_operand [、int $ scale = 0])
- 文字列bcmod(文字列$ left_operand、文字列$モジュラス)
- 文字列bcmul(文字列$ left_operand、文字列$ right_operand [、int $ scale = 0])
- string bcpowmod(文字列$ left_operand、文字列$ right_operand、文字列$モジュラス[、int $ scale = 0])
- bool bcscale(int $ scale)
- 文字列bcsqrt(文字列$ operand [、int $ scale = 0])
- 文字列bcsub(文字列$ left_operand、文字列$ right_operand [、int $ scale = 0])
パラメーター
bcadd | 2つの任意精度の数値を加算する。 |
---|---|
left_operand | 左側のオペランド。文字列です。 |
right_operand | 右のオペランド。文字列です。 |
scale | 結果の小数点以下の桁数を設定するオプションのパラメータ。 |
bccomp | 2つの任意精度の数値を比較する。 |
left_operand | 左側のオペランド。文字列です。 |
right_operand | 右のオペランド。文字列です。 |
scale | 比較に使用される小数点以下の桁数を設定するオプションのパラメータ。 |
bcdiv | 2つの任意の精度の数値を除算します。 |
left_operand | 左側のオペランド。文字列です。 |
right_operand | 右のオペランド。文字列です。 |
scale | 結果の小数点以下の桁数を設定するオプションのパラメータ。 |
bcmod | 任意精度のモジュラスを得る。 |
left_operand | 左側のオペランド。文字列です。 |
modulus | モジュラス(文字列)。 |
bcmul | 2つの任意の精度の数値を掛け合わせます。 |
left_operand | 左側のオペランド。文字列です。 |
right_operand | 右のオペランド。文字列です。 |
scale | 結果の小数点以下の桁数を設定するオプションのパラメータ。 |
bcpow | 任意の精度の数値を別の数値に上げる。 |
left_operand | 左側のオペランド。文字列です。 |
right_operand | 右のオペランド。文字列です。 |
scale | 結果の小数点以下の桁数を設定するオプションのパラメータ。 |
bcpowmod | 任意精度の数値を別の数値に上げ、指定されたモジュラスで縮小します。 |
left_operand | 左側のオペランド。文字列です。 |
right_operand | 右のオペランド。文字列です。 |
modulus | モジュラス(文字列)。 |
scale | 結果の小数点以下の桁数を設定するオプションのパラメータ。 |
bcscale | すべてのbc数学関数のデフォルトのスケールパラメーターを設定します。 |
scale | スケール係数。 |
bcsqrt | 任意の精度の数値の平方根を求めます。 |
operand | オペランド。文字列です。 |
scale | 結果の小数点以下の桁数を設定するオプションのパラメータ。 |
bcsub | 任意の精度の数値を別の精度の数値から差し引く。 |
left_operand | 左側のオペランド。文字列です。 |
right_operand | 右のオペランド。文字列です。 |
scale | 結果の小数点以下の桁数を設定するオプションのパラメータ。 |
備考
すべてのBC関数で、 scale
パラメータが設定されていない場合は、デフォルトで0に設定され、すべての演算が整数演算になります。
BCMathと浮動小数点演算の比較
bcaddとfloat + float
var_dump('10' + '-9.99'); // float(0.0099999999999998)
var_dump(10 + -9.99); // float(0.0099999999999998)
var_dump(10.00 + -9.99); // float(0.0099999999999998)
var_dump(bcadd('10', '-9.99', 20)); // string(22) "0.01000000000000000000"
bcsubとfloat-float
var_dump('10' - '9.99'); // float(0.0099999999999998)
var_dump(10 - 9.99); // float(0.0099999999999998)
var_dump(10.00 - 9.99); // float(0.0099999999999998)
var_dump(bcsub('10', '9.99', 20)); // string(22) "0.01000000000000000000"
bcmulとint * int
var_dump('5.00' * '2.00'); // float(10)
var_dump(5.00 * 2.00); // float(10)
var_dump(bcmul('5.0', '2', 20)); // string(4) "10.0"
var_dump(bcmul('5.000', '2.00', 20)); // string(8) "10.00000"
var_dump(bcmul('5', '2', 20)); // string(2) "10"
bcmulとfloat * float
var_dump('1.6767676767' * '1.6767676767'); // float(2.8115498416259)
var_dump(1.6767676767 * 1.6767676767); // float(2.8115498416259)
var_dump(bcmul('1.6767676767', '1.6767676767', 20)); // string(22) "2.81154984162591572289"
bcdivとfloat / float
var_dump('10' / '3.01'); // float(3.3222591362126)
var_dump(10 / 3.01); // float(3.3222591362126)
var_dump(10.00 / 3.01); // float(3.3222591362126)
var_dump(bcdiv('10', '3.01', 20)); // string(22) "3.32225913621262458471"
bcmathを使用して32ビットシステムでバイナリロングを読み書きする
32ビットシステムでは、 0x7FFFFFFF
より大きい整数はプリミティブに格納できませんが、 0x0000000080000000
と0x7FFFFFFFFFFFFFFF
間の整数は、64ビットシステムではプリミティブに格納できますが、32ビットシステムでsigned long long
整数型( signed long long
)に格納できません。しかし、64ビットシステムや他の多くの言語では、 signed long long
整数の格納がサポートされているため、この整数の範囲を正確な値で格納する必要があることがあります。 2つの数値を持つ配列を作成する、整数を10進数の人間が読める形式に変換するなど、いくつかの方法があります。これには、ユーザーに提示する際の利便性や、bcmathで直接操作する機能など、いくつかの利点があります。
pack
/ unpack
メソッドは、バイナリバイトと数字の小数点形式(型string
両方が1つですが、バイナリと1つはASCIIです)間の変換に使用できますが、ASCII文字列を常に32ビットにキャストしようとします32ビットシステムではintです。次のスニペットは、代替手段を提供します。
/** Use pack("J") or pack("p") for 64-bit systems */
function writeLong(string $ascii) : string {
if(bccomp($ascii, "0") === -1) { // if $ascii < 0
// 18446744073709551616 is equal to (1 << 64)
// remember to add the quotes, or the number will be parsed as a float literal
$ascii = bcadd($ascii, "18446744073709551616");
}
// "n" is big-endian 16-bit unsigned short. Use "v" for small-endian.
return pack("n", bcmod(bcdiv($ascii, "281474976710656"), "65536")) .
pack("n", bcmod(bcdiv($ascii, "4294967296"), "65536")) .
pack("n", bcdiv($ascii, "65536"), "65536")) .
pack("n", bcmod($ascii, "65536"));
}
function readLong(string $binary) : string {
$result = "0";
$result = bcadd($result, unpack("n", substr($binary, 0, 2)));
$result = bcmul($result, "65536");
$result = bcadd($result, unpack("n", substr($binary, 2, 2)));
$result = bcmul($result, "65536");
$result = bcadd($result, unpack("n", substr($binary, 4, 2)));
$result = bcmul($result, "65536");
$result = bcadd($result, unpack("n", substr($binary, 6, 2)));
// if $binary is a signed long long
// 9223372036854775808 is equal to (1 << 63) (note that this expression actually does not work even on 64-bit systems)
if(bccomp($result, "9223372036854775808") !== -1) { // if $result >= 9223372036854775807
$result = bcsub($result, "18446744073709551616"); // $result -= (1 << 64)
}
return $result;
}
Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow