Интересно, есть ли какие-нибудь нетривиальные способы найти знак числа ( signum function )?
Может быть короче / быстрее / элегантнее решения, чем очевидное
var sign = number > 0 ? 1 : number < 0 ? -1 : 0;
Используйте это, и вы будете в безопасности и быстро (источник: moz )
if (!Math.sign) Math.sign = function(x) { return ((x > 0) - (x < 0)) || +x; };
Вы можете посмотреть на производительность и сравнение типов fiddle
Прошло много времени . Дальнейшее происходит в основном по историческим причинам.
На данный момент у нас есть следующие решения:
1. Очевидно и быстро
function sign(x) { return x > 0 ? 1 : x < 0 ? -1 : 0; }
1.1. Модификация из kbec - приведение одного типа меньше, более производительно, короче [самое быстрое]
function sign(x) { return x ? x < 0 ? -1 : 1 : 0; }
предупреждение: знак («0») -> 1
2. Элегантный, короткий, не такой быстрый [самый медленный]
function sign(x) { return x && x / Math.abs(x); }
предупреждение: знак (+ - бесконечность) -> NaN
, знак («0») -> NaN
Поскольку Infinity
является допустимым числом в JS, это решение не кажется полностью правильным.
3. Искусство ... но очень медленное [самое медленное]
function sign(x) { return (x > 0) - (x < 0); }
4. Использование битового сдвига
быстро, но знак (-Infinity) -> 0
function sign(x) { return (x >> 31) + (x > 0 ? 1 : 0); }
5. Типобезопасный [мегабыстрый]
! Похоже, браузеры (особенно chrome v8) делают некоторые волшебные оптимизации, и это решение оказывается намного более производительным, чем другие, даже чем (1.1), несмотря на то, что оно содержит две дополнительные операции и, по логике, никогда не может быть быстрее.
function sign(x) {
return typeof x === 'number' ? x ? x < 0 ? -1 : 1 : x === x ? 0 : NaN : NaN;
}
Улучшения приветствуются!
Андрей Таранцов - +100 за искусство, но к сожалению, это примерно в 5 раз медленнее, чем очевидный подход
Frédéric Hamidi - в каком-то смысле это наиболее одобренный ответ (на момент написания), и это вроде как круто, но это определенно не то, как нужно делать, imho. Кроме того, он неправильно обрабатывает бесконечные числа, которые, как вы знаете, тоже являются числами.
kbec - усовершенствование очевидного решения. Не то чтобы революционно, но в совокупности считаю такой подход лучшим. Проголосуйте за него :)
Math.sign не поддерживается на IE 11. Я комбинирую лучший ответ с ответом Math.sign:
Math.sign = Math.sign || function(number){
var sign = number ? ( (number <0) ? -1 : 1) : 0;
return sign;
};
Теперь, можно использовать Math.sign непосредственно.