非数字の文字列を渡すとき、 BcCompはストリングを比較のために数値に変換しようとします。これは、浮動小数点数または整数の暗黙的な変換に似ています。通常、以下が発生します。
文字列は数字から始まり、非数値文字が続きます。冒頭部分のみが比較のための数字としてとられます。
文字列にはまったく任意の数字が含まれていません。0として処理されます。
例を挙げてください:
<?php
var_dump(bccomp('123abc', '123')); // 出力 0,平等を示します,なぜなら'123abc'考慮されている123
var_dump(bccomp('abc', '0')); // 出力 0,'abc'考慮されている0
var_dump(bccomp('abc', '1')); // 出力 -1,0 < 1
?>
この動作は、特に文字列が数で始まっていない場合、数値以外の文字列を扱うときに誤判断につながる可能性が非常に高いです。
純粋な数値文字列を比較する必要がある場合は、 bccompを使用してください。ただし、文字列に非数値コンテンツが含まれている場合は、最初に次のことを行うことをお勧めします。
is_numericなどのPHPレギュラーまたはビルトイン関数を使用して判断します。
<?php
function safe_bccomp($a, $b, $scale = 0) {
if (!is_numeric($a) || !is_numeric($b)) {
throw new InvalidArgumentException("パラメーターは数値文字列でなければなりません");
}
return bccomp($a, $b, $scale);
}
try {
echo safe_bccomp('123abc', '123'); // 例外を投げます
} catch (InvalidArgumentException $e) {
echo $e->getMessage();
}
?>
これにより、非数字の文字列の誤った比較が0として回避されます。
ビジネスロジックで許可されている場合は、定期的に使用して文字列内の数値パーツのみを抽出してから比較できます。
<?php
function extract_numeric($str) {
preg_match('/^[+-]?(\d+)(\.\d+)?/', $str, $matches);
return $matches[0] ?? '0';
}
$a = extract_numeric('123abc');
$b = extract_numeric('123');
echo bccomp($a, $b); // 0
?>
この方法は、接頭辞に文字列に数値部分がある場合に適しています。
BCCOMPは、デジタルストリング用に設計されています。非数字の文字列が渡されると、それらは自動的に数値に変換され、それが不正確な比較結果につながる可能性があります。
BCCOMPを使用する前に、パラメーターが合法的な数値文字列であるかどうかを確認することをお勧めします。
比較する必要がある文字列に非数値コンテンツが含まれている場合は、最初に例外をフィルタリングまたはスローして、誤判断を避けてください。
合理的な入力検証と前処理を通じてのみ、 BCCOMPが比較して正しく機能することを保証し、予期しない論理エラーを回避できます。
<?php
// フィルター文字列の番号パーツを比較します
function safe_compare($a, $b, $scale = 0) {
preg_match('/^[+-]?(\d+)(\.\d+)?/', $a, $matchA);
preg_match('/^[+-]?(\d+)(\.\d+)?/', $b, $matchB);
$numA = $matchA[0] ?? '0';
$numB = $matchB[0] ?? '0';
return bccomp($numA, $numB, $scale);
}
// 例
echo safe_compare('123abc', '123'); // 出力0
echo safe_compare('abc', '0'); // 出力0
echo safe_compare('abc', '1'); // 出力-1
?>