PHPと同等の gmp_sign
で、数値(整数)の「符号」を取得する(簡単な)方法はありますか?ドキュメント :
これを行うことができるある種の比較機能があることを覚えていますが、現時点ではそれを見つけることができません。
私はすぐにこれをコンパイルしました( Demo )これは仕事をしますが、おそらくもっと気の利いたもの(単一の関数呼び出しのような?)があるので、結果を配列にマッピングしたいと思います。
$numbers = array(-100, 0, 100);
foreach($numbers as $number)
{
echo $number, ': ', $number ? abs($number) / $number : 0, "\n";
}
(このコードはおそらく浮動小数点精度の問題に遭遇するかもしれません)
以下は、効率的かつ確実にそれを実行するクールなワンライナーです。
function sign($n) {
return ($n > 0) - ($n < 0);
}
PHP 7では、 結合された比較演算子 (<=>
):
$sign = $i <=> 0;
私がテストした私の質問の上記の変形であり、同様に機能し、浮動小数点の問題はありません:
min(1, max(-1, $number))
編集:上記のコードには、-1
より大きく1
より小さい範囲の浮動小数点数に関する問題があります(質問は整数についてでした)。これは、次のように修正できます。短い:
min(1, max(-1, $number == 0 ? 0 : $number * INF))
それでも、フロートNAN
に欠陥があり、常に-1
を返します。それは正しくないかもしれません。代わりに、0
も返すことができます。
min(1, max(-1, (is_nan($number) or $number == 0) ? 0 : $number * INF))
三項演算子をネストできます。
echo $number, ': ', ($number >= 0 ? ($number == 0 ? 0 : 1) : -1 )
これは浮動小数点の精度に問題がなく、浮動小数点の除算を回避します。
このフォームの何が問題になっていますか?
_if ( $num < 0 )
{
//negative
}
else if ( $num == 0 )
{
//zero
}
else
{
//positive
}
_
または三項:
_$sign = $num < 0 ? -1 : ( $num > 0 ? 1 : 0 );
_
abs
と値の比較のパフォーマンスはわかりませんが、次のものを使用できます。
_$sign = $num ? $num / abs($num) : 0;
_
そして、あなたはそれらのいずれかを関数に変えることができます:
_function valueSign($num)
{
return $sign = $num < 0 ? -1 : ( $num > 0 ? 1 : 0 );
//or
return $sign = $num ? $num / abs($num) : 0;
}
_
私はあなたが _gmp_cmp
_ について話している可能性があると思います、それはgmp_cmp( $num, 0 );
として呼び出すことができます
Gmp_signはGMPまたは文字列を想定しているため、あまり効率的ではないと思います。 ($ n?abs($ n)/ $ n:0)は数学的に正しいですが、除算には時間がかかります。最小/最大解は、フロートにとって不必要に複雑になるようです。
($ n> 0)-($ n <0)は常に2つのテストと1つの減算を実行します($ n <0?-1:($ n> 0?1:0)は1つまたは2つのテストを実行し、算術演算は行いません。最も効果的ですが、違いがほとんどのユースケースに関連するとは思いません。
私はこれが遅いことを知っていますが、数をそれ自体のabs()で単純に除算するとどうでしょうか?
何かのようなもの:
function sign($n) {
return $n/(abs($n));
}
Divに必要なエラー処理をゼロで配置します。
echo $number, ': ', strcmp($number, 0), "\n";
これはループのないものです:
function sign($number){
echo $number, ': ', $number ? abs($number) / $number : 0, "\n";
}
$numbers = array(-100, 0, 100);
array_walk($numbers, 'sign');