Как получить знак числа?
есть ли (простой) способ получить "знак" числа (целого числа) в PHP, сопоставимого с gmp_sign
Docs:
- -1 отрицательный
- 0 ноль
- 1 положительный
Я помню, что есть какая-то функция сравнения, которая может это сделать, но я не могу найти ее на данный момент.
я быстро собрал эту (демо), который делает работу, но, возможно, есть что-то более изящное (например, вызов одной функции?), Я хотел бы отобразить результат на массив:
$numbers = array(-100, 0, 100);
foreach($numbers as $number)
{
echo $number, ': ', $number ? abs($number) / $number : 0, "n";
}
(этот код может столкнуться с проблемами точности с плавающей запятой, вероятно)
9 ответов
вот классный One-liner, который сделает это для вас эффективно и надежно:
function sign($n) {
return ($n > 0) - ($n < 0);
}
в PHP 7 Вы должны использовать комбинированный оператор сравнения (<=>
):
$sign = $i <=> 0;
вариант выше в моем вопросе, который я тестировал и который также работает и не имеет проблемы с плавающей запятой:
min(1, max(-1, $number))
Edit: код выше имеет недостаток для чисел float (вопрос был о целых числах) в диапазоне, большем, чем -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
vs сравнение значений, но вы можете использовать:
$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) математически корректен, но деление стоит времени. Решения min/max, похоже, становятся ненужными для поплавков.
($n > 0) - ($n 0 ? 1: 0) делает один или два теста и никакой арифметики, он должен быть наиболее эффективным. Но я не верю, что разница будет актуальна для большинства случаев использования.
Я знаю, что это поздно, но как насчет простого деления числа на abs () самого по себе?
что-то типа:
function sign($n) {
return $n/(abs($n));
}
поместите любую обработку ошибок, которую вы хотите для div, на ноль.
вот один без цикла:
function sign($number){
echo $number, ': ', $number ? abs($number) / $number : 0, "\n";
}
$numbers = array(-100, 0, 100);
array_walk($numbers, 'sign');