Gostaria de saber se existem maneiras não triviais de encontrar o sinal de número ( função signum )?
Podem ser soluções mais curtas / rápidas / mais elegantes do que a óbvia
var sign = number > 0 ? 1 : number < 0 ? -1 : 0;
Resposta curta!
Use isso e você estará seguro e rápido (fonte: moz )
if (!Math.sign) Math.sign = function(x) { return ((x > 0) - (x < 0)) || +x; };
Você pode querer observar o desempenho e o violino de comparação de coerção de tipo
Muito tempo se passou. Além disso, é principalmente por razões históricas.
Resultados
Por enquanto, temos estas soluções:
1. Óbvio e rápido
function sign(x) { return x > 0 ? 1 : x < 0 ? -1 : 0; }
1.1. Modificação de kbec - um tipo de elenco a menos, mais desempenho, mais curto [mais rápido]
function sign(x) { return x ? x < 0 ? -1 : 1 : 0; }
Cuidado: sign("0") -> 1
2. Elegante, curto, não tão rápido [mais lento]
function sign(x) { return x && x / Math.abs(x); }
CUIDADO: sign(+-Infinity) -> NaN
,sign("0") -> NaN
Como Infinity
é um número legal em JS, essa solução não parece totalmente correta.
3. A arte ... mas muito lenta [mais lenta]
function sign(x) { return (x > 0) - (x < 0); }
4. Usando bit-shift
rápido, massign(-Infinity) -> 0
function sign(x) { return (x >> 31) + (x > 0 ? 1 : 0); }
5. Tipo seguro [megafast]
! Parece que os navegadores (especialmente o Chrome v8) fazem algumas otimizações mágicas e esta solução acaba tendo muito mais desempenho do que outras, até mesmo do que (1.1), apesar de conter 2 operações extras e logicamente nunca pode ser mais rápida.
function sign(x) {
return typeof x === 'number' ? x ? x < 0 ? -1 : 1 : x === x ? 0 : NaN : NaN;
}
Ferramentas
- testes de desempenho jsperf ;
- violino - testes de tipo fundido;
Melhorias são bem-vindas!
[Offtopic] Resposta aceita
Andrey Tarantsov - +100 para a arte, mas infelizmente é cerca de 5 vezes mais lento do que a abordagem óbvia
Frédéric Hamidi - de alguma forma a resposta mais votada (por enquanto) e é bem legal, mas definitivamente não é como as coisas deveriam ser feitas, imho. Além disso, ele não lida corretamente com números do Infinity, que também são números, você sabe.
kbec - é uma melhoria da solução óbvia. Não tão revolucionário, mas no conjunto considero esta abordagem a melhor. Vote nele :)
test everything
versão, o Safe se recusará a testar os valores especiais, então será mais rápido! Em only integers
vez disso, tente executar o teste. Além disso, JSPerf está apenas fazendo seu trabalho, não é uma questão de gostar. :)
typeof x === "number"
coloca um pouco de mágica na performance. Por favor, faça mais execuções, especialmente FF, Opera e IE para deixar isso claro.
Math.sign()
(0 === 0, não tão rápido quanto "Seguro") que apareceu no FF25 e será lançado no Chrome.
0
é um caso especial