Number.sign () in Javascript
Frage mich, ob es irgendwelche nicht-triviale Wege zu finden, die Anzahl der Zeichen (signum-Funktion)?
Kann sein, kürzere /schnellere /elegantere Lösungen als die offensichtliche
var sign = number > 0 ? 1 : number < 0 ? -1 : 0;
Kurzer Auszug
Verwenden Sie diese und Sie werden schnell und sicher
function sign(x) {
return typeof x === 'number' ? x ? x < 0 ? -1 : 1 : x === x ? 0 : NaN : NaN;
}
Ergebnisse
Für jetzt haben wir diese Lösungen:
1. Offensichtlich und schnell
function sign(x) { return x > 0 ? 1 : x < 0 ? -1 : 0; }
1.1. Änderung von kbec - eine Art cast-weniger, schneller, kürzer [Schnellste]
function sign(x) { return x ? x < 0 ? -1 : 1 : 0; }
Vorsicht: sign("0") -> 1
2. Elegante, kurze, nicht so schnell [langsamsten]
function sign(x) { return x && x / Math.abs(x); }
Vorsicht: sign(+-Infinity) -> NaN
sign("0") -> NaN
Als der Infinity
ist eine juristische Zahl in JS diese Lösung scheint nicht ganz korrekt.
3. Die Kunst... aber sehr langsam [langsamsten]
function sign(x) { return (x > 0) - (x < 0); }
4. Unter Verwendung von bit-shift
schnell, aber sign(-Infinity) -> 0
function sign(x) { return (x >> 31) + (x > 0 ? 1 : 0); }
5. Typ-sicher [megafast]
! Scheint, wie Browser (vor allem chrome ' s v8) machen Sie einige Magische Optimierungen und diese Lösung stellt sich heraus, dass sehr viel leistungsfähiger als andere, auch als (1.1), obwohl es enthält 2 zusätzliche Operationen und logischerweise nie kann nicht schneller sein.
function sign(x) {
return typeof x === 'number' ? x ? x < 0 ? -1 : 1 : x === x ? 0 : NaN : NaN;
}
Tools
Verbesserungen sind willkommen!
[Offtopic] Akzeptierte Antwort
- Andrey Tarantsov - +100 für die Kunst, aber leider es ist etwa 5-mal langsamer als die offensichtliche Ansatz
- Frédéric Hamidi - irgendwie sind die meisten von Ihnen positiv bewertet werden Antwort (für die Zeit zu schreiben) und es ist echt cool, aber es ist definitiv nicht so, wie die Dinge getan werden sollte, imho. Auch ist es nicht richtig verarbeiten Infinity-zahlen, die auch zahlen, wissen Sie.
- kbec - ist eine Verbesserung der offensichtlichen Lösung. Nicht Revolutionär, aber alles zusammen halte ich diesen Ansatz am besten. Für ihn Stimmen 🙂
InformationsquelleAutor der Frage |
Du musst angemeldet sein, um einen Kommentar abzugeben.
Elegantere version der schnellen Lösung:
InformationsquelleAutor der Antwort kbec
Division der Zahl durch seinen absoluten Wert gibt auch das Vorzeichen. Mit der short-circuiting logischen UND-operator können Sie uns zu speziellen-Fall
0
damit wir nicht am Ende der Division durch:InformationsquelleAutor der Antwort Frédéric Hamidi
Die Funktion die du suchst heißt signumund der beste Weg, um es zu implementieren ist:
InformationsquelleAutor der Antwort Andrey Tarantsov
Sollte dies nicht die Unterstützung von JavaScript (ECMAScript) unterzeichnet Nullen? Es scheint zu funktionieren, wenn wieder x statt 0 in der "megafast" - Funktion:
Dies macht es kompatibel mit dem Entwurf des ECMAScript-Math.melden (MDN):
InformationsquelleAutor der Antwort
Für Menschen, die interessiert, was Los ist mit den neuesten Browsern, in ES6-version gibt es eine native Math.melden Methode. Sie können die support hier.
Grundsätzlich gibt es
-1
1
0
oderNaN
InformationsquelleAutor der Antwort
Superfast wenn Sie nicht brauchen, Infinity und wissen, dass die Zahl eine ganze Zahl ist, fand in openjdk-7-source:
java.lang.Integer.signum()
InformationsquelleAutor der Antwort
Ich dachte, ich würde hinzufügen, das nur für Spaß:
0 und NaN wird -1 zurück
funktioniert gut auf +/-Infinity
InformationsquelleAutor der Antwort
Eine Lösung, die funktioniert auf allen Nummern, sowie
0
und-0
sowieInfinity
und-Infinity
ist:Finden Sie unter der Frage "Gibt +0 und -0 die gleiche?" für weitere Informationen.
Warnung: Keine dieser Antworten, darunter die mittlerweile zum standard
Math.Zeichen
wird die Arbeit auf den Fall0
vs-0
. Dies kann nicht ein Problem für Sie, aber in bestimmten Physik-Implementierungen kann es auch egal.InformationsquelleAutor der Antwort
Könnten Sie bit-Verschiebung die Anzahl und überprüfen Sie die Most Significant Bit (MSB). Wenn das MSB eine 1 ist, dann ist die Zahl negativ. Wenn es 0 ist die Zahl positiv (oder 0).
InformationsquelleAutor der Antwort Brombomb
Ich war nur über die gleiche Frage stellen, kam aber zu einer Lösung war, bevor ich mit dem schreiben fertig, sah diese Frage gab es schon, aber nicht sah diese Lösung.
(n >> 31) + (n > 0)
es scheint schneller zu sein, durch hinzufügen eines ternären obwohl
(n >> 31) + (n>0?1:0)
InformationsquelleAutor der Antwort Moritz Roessler
Sehr ähnlich Martijn Antwort ist
Ich finde es besser lesbar. Auch (oder, je nach Sicht, jedoch), die es auch groks Dinge, die interpretiert werden kann als eine Zahl; z.B., es gibt
-1
wenn Sie mit vorgestellt'-5'
.InformationsquelleAutor der Antwort
Sehe ich keinen praktischen Sinn der Rücksendung -0 und 0 von
Math.sign
also meine version ist:InformationsquelleAutor der Antwort
Den Methoden, die ich kenne sind wie folgt:
Math.Zeichen(n)
var s = Math.sign(n)
Dies ist die native Funktion, aber am langsamsten von allen, weil der overhead eines Funktionsaufrufs. Es hat jedoch Griff 'NaN', wo der andere unter Umständen einfach annehmen, dass 0 (d.h. Math.Zeichen('abc') "NaN").
((n>0) - (n<0))
var s = ((n>0) - (n<0));
In diesem Fall nur von der linken oder rechten Seite kann ein 1 basierend auf dem Schild. Dies führt entweder
1-0
(1),0-1
(-1), oder0-0
(0).Die Geschwindigkeit dieser scheint man Hals und Nacken mit den weiter unten in Chrom.
(n>>31)|(!!n)
var s = (n>>31)|(!!n);
Nutzt die "Melden-Vermehrung shift rechts". Grundsätzlich ist die Verlagerung von 31 Tropfen alle bits außer dem Schild. Wenn das Zeichen gesetzt wurde, diese Ergebnisse in -1, ansonsten ist es 0. Rechts
|
es tests für positive durch die Umwandlung der Wert in den Typ boolean (0 oder 1 [BTW: nicht-numerische Zeichenfolgen, wie!!'abc'
werden in diesem Fall 0, und nicht NaN]) und verwendet dann eine bitweise ODER-operation kombinieren der bits.Scheint dies die beste Durchschnittliche Leistung über den Browser (am besten in Chrome und Firefox zumindest), aber nicht der Schnellste in ALLE von Ihnen. Für einige Grund, der ternäre operator ist schneller im IE.
n?n<0?-1:1:0
var s = n?n<0?-1:1:0;
Schnellste im IE aus irgendeinem Grund.
jsPerf
Tests durchgeführt: https://jsperf.com/get-sign-from-value
InformationsquelleAutor der Antwort
Meine zwei Cent, mit einer Funktion, die liefert die gleichen Ergebnisse wie die Mathematik.Zeichen tun würde, dh das Vorzeichen(-0) --> -0, - Zeichen(-Unendlich) --> -Infinity, Zeichen(null) --> 0, sign(undefined) --> NaN, etc.
Jsperf nicht lassen Sie mich einen test erstellen oder überarbeitung, sorry für nicht in der Lage, Ihnen mit tests (ich habe da jsbench.github.io versucht, aber die Ergebnisse scheinen sehr viel näher zu einander, als mit Jsperf...)
Wenn jemand könnte, bitte fügen Sie es ein Jsperf-revision, ich wäre neugierig zu sehen, wie es im Vergleich zu allen bisher gegebenen Lösungen...
Danke!
Jim.
BEARBEITEN:
Ich soll geschrieben haben:
(
(+x && -1)
statt(x && -1)
) umsign('abc')
richtig (--> NaN)InformationsquelleAutor der Antwort