Подтвердить что ты не робот

Как получить знак номера?

Есть ли (простой) способ получить "знак" числа (целое число) в PHP, сопоставимый с gmp_sign Docs:

  • -1 отрицательный
  • 0 zero
  • 1 положительный

Я помню, что есть какая-то функция сравнения, которая может это сделать, но я не могу ее найти в данный момент.

Я быстро скомпилировал это (Demo), который выполняет эту работу, но может быть, есть что-то более изящное (например, вызов одной функции?), Я хотел бы сопоставить результат с массивом:

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

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

(этот код может, вероятно, столкнуться с проблемами точности с плавающей запятой)

Связанный: ЗапроС# 19621 Математика нуждается в функции" sign()

4b9b3361

Ответ 1

Здесь крутой однострочный, который сделает это для вас эффективно и надежно:

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

Ответ 2

Вариант выше в моем вопросе, который я тестировал, и который также работает и не имеет проблемы с плавающей запятой:

min(1, max(-1, $number))

Изменить: приведенный выше код имеет недостаток для чисел с плавающей запятой (вопрос о целочисленных числах) в диапазоне больше -1 и меньше 1, который может быть исправлен следующим коротким:

min(1, max(-1, $number == 0 ? 0 : $number * INF))

У этого все еще есть недостаток для float NAN, заставляющий его всегда возвращать -1. Это может быть неверно. Вместо этого можно также возвращать 0:

min(1, max(-1, (is_nan($number) or $number == 0) ? 0 : $number * INF))

Ответ 4

Вы можете вложить тройные операторы:

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

Это не имеет проблем с точностью с плавающей запятой и позволяет избежать деления с плавающей запятой.

Ответ 5

Что не так с этой формой?

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

Я думаю, что gmp_sign не очень эффективен, потому что он ожидает GMP или строку. ($ n? abs ($ n)/$n: 0) математически корректно, но разделение требует времени. Решения min/max кажутся излишне сложными для поплавков.

($ n > 0) - ($ n < 0) всегда выполняет 2 теста и одно вычитание ($ n < 0? -1: ($ n > 0? 1: 0) выполняет один или два теста и не имеет арифметики, он должен быть наиболее эффективным. Но я не считаю, что разница будет иметь значение для большинства случаев использования.

Ответ 7

Я знаю, что это поздно, но как просто делить число на abs() самого себя?

Что-то вроде:

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

Поместите любую обработку ошибок, которую вы хотите для div на ноль.

Ответ 9

Здесь один без цикла:

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

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

array_walk($numbers, 'sign');