web-dev-qa-db-ja.com

番号のサインを取得するには?

PHPと同等の gmp_signで、数値(整数)の「符号」を取得する(簡単な)方法はありますか?ドキュメント

  • マイナス1
  • 0ゼロ
  • 1ポジティブ

これを行うことができるある種の比較機能があることを覚えていますが、現時点ではそれを見つけることができません。

私はすぐにこれをコンパイルしました( Demo )これは仕事をしますが、おそらくもっと気の利いたもの(単一の関数呼び出しのような?)があるので、結果を配列にマッピングしたいと思います。

$numbers = array(-100, 0, 100);

foreach($numbers as $number)
{
   echo $number, ': ', $number ? abs($number) / $number : 0, "\n";
}

(このコードはおそらく浮動小数点精度の問題に遭遇するかもしれません)

関連: リクエスト#19621数学には「sign()」関数が必要

33
hakre

以下は、効率的かつ確実にそれを実行するクールなワンライナーです。

function sign($n) {
    return ($n > 0) - ($n < 0);
}
52
Milosz

PHP 7では、 結合された比較演算子<=>):

$sign = $i <=> 0;
30
Peping

私がテストした私の質問の上記の変形であり、同様に機能し、浮動小数点の問題はありません:

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))
17
hakre

三項演算子をネストできます。

echo $number, ': ',  ($number >= 0 ? ($number == 0 ? 0 : 1) : -1 )

これは浮動小数点の精度に問題がなく、浮動小数点の除算を回避します。

9
rocksportrocker

このフォームの何が問題になっていますか?

_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 );として呼び出すことができます

6
zzzzBov

Gmp_signはGMPまたは文字列を想定しているため、あまり効率的ではないと思います。 ($ n?abs($ n)/ $ n:0)は数学的に正しいですが、除算には時間がかかります。最小/最大解は、フロートにとって不必要に複雑になるようです。

($ n> 0)-($ n <0)は常に2つのテストと1つの減算を実行します($ n <0?-1:($ n> 0?1:0)は1つまたは2つのテストを実行し、算術演算は行いません。最も効果的ですが、違いがほとんどのユースケースに関連するとは思いません。

4
Rolf

私はこれが遅いことを知っていますが、数をそれ自体のabs()で単純に除算するとどうでしょうか?

何かのようなもの:

function sign($n) {
    return $n/(abs($n));
}

Divに必要なエラー処理をゼロで配置します。

3
sansig

strcmpを使用しますドキュメント

echo $number, ': ', strcmp($number, 0), "\n";
2
Toto

これはループのないものです:

function sign($number){
    echo $number, ': ', $number ? abs($number) / $number : 0, "\n";
}

$numbers = array(-100, 0, 100);

array_walk($numbers, 'sign');
1
Yeroon