2013-06-12 10 views
5

Voglio rimuovere il segno di un numero in JavaScript. Questi sono i casi di test che già esaminati in jsperf (http://jsperf.com/remove-sign-from-number)Veloce e risparmia il modo di rimuovere il segno di un numero inedito in JavaScript

if(n < 0) n *= -1; 

if(n < 0) n = -n; 

n = Math.abs(n) 

(n < 0) && (n *= -1) 

(n < 0) && (n = -n) 

n = Math.sqrt(n*n) 

Secondo queste prove: if(n < 0) n *= -1 sembra essere una buona soluzione.

Conoscete un modo migliore, più efficiente e più efficiente per farlo?

Edit 1: Math.sqrt caso di Aggiunto Nikhil, ma sqrt di solito è piuttosto lento nella maggior parte dei sistemi.

Edit 2: la proposta di Jan per ops bit a bit può essere più veloce in alcuni casi, ma anche rimuovere cifre frazionarie, e quindi non funziona per me.

+1

Caratteristiche prestazionali variano ampiamente tra i browser. Su SeaMonkey, 'Math.abs' chiaramente supera tutti gli altri. Su Konqueror, bitwise ('if (n <0) n = ~ n + 1') brilla [le varianti' && 'sono tutte negative] e' Math.abs' fa schifo. Tutto sommato, 'if (n <0) n * = -1' e' if (n <0) n = -n' sembrano essere quelli sicuri che non puzzano troppo male ovunque. Un problema con gli operatori bit a bit è che impongono il numero in un numero intero a 32 bit - se "n" non rientra in tale intervallo, la modalità bit a bit produrrebbe spazzatura. –

risposta

0

è anche possibile utilizzare n = Math.sqrt (n^n)

+0

Immagino tu intendessi 'Math.sqrt (n * n)'? L'ho aggiunto ai miei casi, ma è molto più lento degli altri. – Juve

1

operatori bit per bit sono i più veloci, vedere the results.

if(n < 0) n = ~n+1; 
+1

Posso chiederti perché hai bisogno di questo in javascript? Javascript non dovrebbe essere la lingua più veloce. Perché non usare C o Assembly? –

+0

Sto implementando un piccolo motore di gioco proof-of-concept in CoffeeScript e ho bisogno di questa rimozione di segno per alcuni calcoli interni. La tua risposta sembra promettente (anche se continuerei a seguire l'if-then * = -1) che sembra essere un'opzione migliore per una buona valutazione. prestazioni su browser e esp. per leggibilità. Se spieghi che cosa fa il tuo codice in dettaglio e come fornisce risultati corretti (rimuovi il segno e conservi il valore), potrei accettarlo come risposta. I dettagli sono sempre buoni, esp. per tutti gli altri lettori. Non tutti conoscono bene le operazioni bitwise, esp. nella comunità Javascript. – Juve

+0

Scusa, ho appena testato alcuni valori e la tua soluzione converte anche i floatt JS in "ints" (Sì, so che JS utilizza solo float). Non è quello che volevo. Devo rimuovere anche il segno dai numeri non fissi. :( – Juve

1

Dal momento che nessuna risposta migliore è apparso io riassumere i risultati in questa risposta me stesso.

  1. if(n < 0) n *= -1 è attualmente la scelta migliore. Funziona abbastanza bene sulla maggior parte delle piattaforme ed è molto leggibile. Conserva anche le frazioni decimali.
  2. Altre varianti, come n = Math.abs(n), potrebbero essere più veloci su altre piattaforme. Ma il guadagno è di solito solo di poche percentuali. Si può prendere in considerazione la possibilità di rilevare il browser/la piattaforma in anticipo e creare un codice dipendente dalla piattaforma che utilizza l'una o l'altra variante. Questo può darti le migliori prestazioni su ogni piattaforma ma introduce un sacco di spese generali.
  3. Fare attenzione quando si considerano operatori bit a bit, potrebbero essere più veloci su alcune piattaforme, ma possono cambiare la semantica del programma (rimuovendo le frazioni decimali).
0

Ecco un altro modo:

n * (n>>31|!!n) (non necessariamente il più veloce in tutti i browser, solo un altro modo)

Questo darà sempre un numero positivo. Fondamentalmente, >> sposta tutti i bit e mantiene il segno. Quello è quindi OR bit a bit con 0 o 1 (se invece è positivo), producendo o -1, 0 o 1. Ciò significa che il segno si moltiplica da solo, rendendolo sempre uniforme.

O anche con semplici operazioni ternari:

n * (n < 0 ? -1 : 1)

o

n = n < 0 ? -n : n

Il secondo sembra costantemente veloci tutti i browser, come alcuni altri dalla originale jsPerf del PO: n > 0 || (n *= -1) e n < 0 && (n = -n), che sono anche costantemente veloci.

jsPerf: https://jsperf.com/remove-sign-from-a-number

Problemi correlati