Ответ 1
Здесь крутой однострочный, который сделает это для вас эффективно и надежно:
function sign($n) {
return ($n > 0) - ($n < 0);
}
Есть ли (простой) способ получить "знак" числа (целое число) в PHP, сопоставимый с gmp_sign
Docs:
Я помню, что есть какая-то функция сравнения, которая может это сделать, но я не могу ее найти в данный момент.
Я быстро скомпилировал это (Demo), который выполняет эту работу, но может быть, есть что-то более изящное (например, вызов одной функции?), Я хотел бы сопоставить результат с массивом:
$numbers = array(-100, 0, 100);
foreach($numbers as $number)
{
echo $number, ': ', $number ? abs($number) / $number : 0, "\n";
}
(этот код может, вероятно, столкнуться с проблемами точности с плавающей запятой)
Связанный: ЗапроС# 19621 Математика нуждается в функции" sign()
Здесь крутой однострочный, который сделает это для вас эффективно и надежно:
function sign($n) {
return ($n > 0) - ($n < 0);
}
Вариант выше в моем вопросе, который я тестировал, и который также работает и не имеет проблемы с плавающей запятой:
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))
В PHP 7 вы должны использовать комбинированный оператор сравнения (<=>
):
$sign = $i <=> 0;
Вы можете вложить тройные операторы:
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) математически корректно, но разделение требует времени. Решения min/max кажутся излишне сложными для поплавков.
($ n > 0) - ($ n < 0) всегда выполняет 2 теста и одно вычитание ($ n < 0? -1: ($ n > 0? 1: 0) выполняет один или два теста и не имеет арифметики, он должен быть наиболее эффективным. Но я не считаю, что разница будет иметь значение для большинства случаев использования.
Я знаю, что это поздно, но как просто делить число на abs() самого себя?
Что-то вроде:
function sign($n) {
return $n/(abs($n));
}
Поместите любую обработку ошибок, которую вы хотите для div на ноль.
Используйте strcmp
Документы:
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');