Antworten:
Berechnen Sie für eine Zahl y
und einen Teiler x
den Quotienten ( quotient
) und den Rest ( remainder
) wie folgt :
var quotient = Math.floor(y/x);
var remainder = y % x;
floor
und %
zusammen ist auf diese Weise nicht konsistent. Verwenden Sie entweder trunc
anstelle von floor
(wodurch negative Reste zugelassen werden) oder verwenden Sie die Subtraktion, um den Rest zu erhalten ( rem = y - div * x
).
rem
trotzdem berechnen möchten, können Sie den Quotienten div
schneller ohne Bodenbelag erhalten : (y - rem) / x
. 2. Übrigens ist die Modulo-Operation nach Donald Knuths empfohlener Definition (Vorzeichen-Übereinstimmungs-Divisor, nicht der Rest, dh der euklidische Modul, noch die JavaScript-Vorzeichen-Übereinstimmungs-Dividende) das, was wir in JavaScript codieren können function mod (a, n) { return a % n + (Math.sign(a) !== Math.sign(n) ? n : 0); }
.
Ich bin kein Experte für bitweise Operatoren, aber hier ist eine andere Möglichkeit, die ganze Zahl zu erhalten:
var num = ~~(a / b);
Dies funktioniert auch bei negativen Zahlen einwandfrei, während Math.floor()
in die falsche Richtung gerundet wird.
Dies scheint auch richtig zu sein:
var num = (a / b) >> 0;
a/b | 0
~~int
, int | 0
Und int >> 0
ändert nicht anfängliches Argument, sondern Dolmetscher integralen Bestandteils an Betreibern Pass.
floor
dreht sich angesichts seines Namens kaum in die falsche Richtung - nur nicht in die Richtung, die die Leute im Allgemeinen wollen!
a = 12447132275286670000; b = 128
Math.floor(a/b)
-> 97243220900677100
und ~~(a/b)
-> -1231452688
.
~~(5/2) --> 2
wie auch (5/2)>>0 --> 2
, aber ~~(5/2) + 1 --> 3
während ~~(5/2)>>0 + 1 --> 1
. ~~
ist eine gute Wahl, da der Vorrang angemessener ist.
Ich habe einige Geschwindigkeitstests mit Firefox durchgeführt.
-100/3 // -33.33..., 0.3663 millisec
Math.floor(-100/3) // -34, 0.5016 millisec
~~(-100/3) // -33, 0.3619 millisec
(-100/3>>0) // -33, 0.3632 millisec
(-100/3|0) // -33, 0.3856 millisec
(-100-(-100%3))/3 // -33, 0.3591 millisec
/* a=-100, b=3 */
a/b // -33.33..., 0.4863 millisec
Math.floor(a/b) // -34, 0.6019 millisec
~~(a/b) // -33, 0.5148 millisec
(a/b>>0) // -33, 0.5048 millisec
(a/b|0) // -33, 0.5078 millisec
(a-(a%b))/b // -33, 0.6649 millisec
Das Obige basiert auf jeweils 10 Millionen Versuchen.
Schlussfolgerung: Verwenden Sie (a/b>>0)
(oder (~~(a/b))
oder (a/b|0)
), um einen Effizienzgewinn von ca. 20% zu erzielen. Denken Sie auch daran, dass sie alle nicht mit dem Math.floor
Zeitpunkt übereinstimmen a/b<0 && a%b!=0
.
Math.floor
und wer-weiß-wie-viele andere API-Funktionen oder Lernen über den ~
(bitweise-nicht) Operator und wie bitweise Operationen in JS funktionieren und dann den Effekt von Double Tilde verstehen ?
Math.floor
besser verstehen . Und selbst wenn nicht, ist dieser googleable.
ES6 führt die neue Math.trunc
Methode ein. Auf diese Weise kann die Antwort von @ MarkElliot korrigiert werden , damit sie auch für negative Zahlen funktioniert:
var div = Math.trunc(y/x);
var rem = y % x;
Beachten Sie, dass Math
Methoden gegenüber bitweisen Operatoren den Vorteil haben, dass sie mit Zahlen über 2 31 arbeiten .
18014398509481984 == 18014398509481985
.
~~(x/y)
. Müssen größere Zahlen bis zu 54 Bit signiert unterstützt werden? Verwenden Math.trunc
Sie es, wenn Sie es haben oder auf Math.floor
andere Weise (korrekt für negative Zahlen). Müssen Sie noch größere Zahlen unterstützen? Verwenden Sie eine große Zahlenbibliothek.
divmod
können Sie es als solches implementieren:function divmod(x, y) { var div = Math.trunc(x/y); var rem = x % y; return [div, rem]; }
var remainder = x % y;
return (x - remainder) / y;
Math.trunc
:) verwendet. Ich habe mit 100,3 nachgefragt; -100,3; 100, -3 und -100, -3. Natürlich ist viel Zeit vergangen, seit sich Ihr Kommentar und die Dinge geändert haben.
Ich benutze normalerweise:
const quotient = (a - a % b) / b;
const remainder = a % b;
Es ist wahrscheinlich nicht das eleganteste, aber es funktioniert.
Sie können die Funktion verwenden parseInt
, um ein abgeschnittenes Ergebnis zu erhalten.
parseInt(a/b)
Verwenden Sie den Mod-Operator, um einen Rest zu erhalten:
a%b
parseInt hat einige Fallstricke mit Strings, um die Verwendung von Radix-Parametern mit Basis 10 zu vermeiden
parseInt("09", 10)
In einigen Fällen kann die Zeichenfolgendarstellung der Zahl eine wissenschaftliche Notation sein. In diesem Fall führt parseInt zu einem falschen Ergebnis.
parseInt(100000000000000000000000000000000, 10) // 1e+32
Dieser Aufruf erzeugt 1 als Ergebnis.
parseInt
sollte nach Möglichkeit vermieden werden. Hier ist Douglas Crockfords Warnung: "Wenn das erste Zeichen der Zeichenfolge 0 ist, wird die Zeichenfolge in Basis 8 anstelle von Basis 10 ausgewertet. In Basis 8 sind 8 und 9 keine Ziffern, also parseInt (" 08 ") und parseInt ("09") erzeugen 0 als Ergebnis. Dieser Fehler verursacht Probleme in Programmen, die Datums- und Uhrzeitangaben analysieren. Glücklicherweise kann parseInt einen Radix-Parameter verwenden, sodass parseInt ("08", 10) 8 erzeugt. Ich empfehle dies immer Geben Sie den Radix-Parameter an. " archive.oreilly.com/pub/a/javascript/excerpts/…
parseInt
dass vermieden werden sollte; nur, dass es einige Fallstricke gibt, die man beachten muss. Sie müssen sich dieser Dinge bewusst sein und bereit sein, damit umzugehen.
parseInt
mit einem Zahlenargument an. parseInt
soll teilweise numerische Zeichenfolgen analysieren, keine Zahlen abschneiden.
JavaScript berechnet den Boden der negativen Zahlen und den Rest der nicht ganzzahligen Zahlen nach den mathematischen Definitionen für sie.
FLOOR ist definiert als "die größte Ganzzahl, die kleiner als der Parameter ist", also:
REST bleibt definiert als "Rest" einer Division (euklidische Arithmetik). Wenn die Dividende keine ganze Zahl ist, ist der Quotient normalerweise auch keine ganze Zahl, dh es gibt keinen Rest, aber wenn der Quotient gezwungen ist, eine ganze Zahl zu sein (und das passiert, wenn jemand versucht, den Rest oder den Modul von a zu erhalten Gleitkommazahl), es wird offensichtlich eine Nicht-Ganzzahl "übrig" sein.
JavaScript berechnet alles wie erwartet, daher muss der Programmierer darauf achten, die richtigen Fragen zu stellen (und die Leute sollten darauf achten, die gestellten Fragen zu beantworten!). Yarins erste Frage lautete NICHT "Was ist die ganzzahlige Division von X durch Y", sondern stattdessen "geht die GANZE Häufigkeit, mit der eine bestimmte Ganzzahl in eine andere übergeht". Für positive Zahlen ist die Antwort für beide gleich, jedoch nicht für negative Zahlen, da die ganzzahlige Division (Dividende durch Divisor) -1 kleiner ist als die Zeiten, in denen eine Zahl (Divisor) in eine andere "geht" (Dividende). Mit anderen Worten, FLOOR gibt die richtige Antwort für eine ganzzahlige Division einer negativen Zahl zurück, aber Yarin hat das nicht gefragt!
gammax antwortete richtig, dieser Code funktioniert wie von Yarin gefragt. Auf der anderen Seite liegt Samuel falsch, er hat wohl nicht nachgerechnet, oder er hätte gesehen, dass es funktioniert (außerdem hat er nicht gesagt, was der Teiler seines Beispiels war, aber ich hoffe, es war 3):
Rest = X% Y = -100% 3 = -1
GoesInto = (X - Rest) / Y = (-100 - -1) / 3 = -99 / 3 = -33
Übrigens habe ich den Code unter Firefox 27.0.1 getestet. Er funktionierte wie erwartet, mit positiven und negativen Zahlen sowie mit nicht ganzzahligen Werten, sowohl für Dividenden als auch für Divisoren. Beispiel:
-100,34 / 3,57: GoesInto = -28, Rest = -0,3800000000000079
Ja, ich habe festgestellt, dass es dort ein Präzisionsproblem gibt, aber ich hatte keine Zeit, es zu überprüfen (ich weiß nicht, ob es ein Problem mit Firefox, Windows 7 oder der FPU meiner CPU ist). Für Yarins Frage, die nur ganze Zahlen enthält, funktioniert der Gammax-Code jedoch perfekt.
Math.floor(operation)
Gibt den abgerundeten Wert der Operation zurück.
Beispiel 1 st Frage:
var x = 5;
var y = 10.4;
var z = Math.floor(x + y);
console.log(z);
Konsole:
fünfzehn
Beispiel 2 nd Frage:
var x = 14;
var y = 5;
var z = Math.floor(x%y);
console.log(x);
Konsole:
4
Die Berechnung der Anzahl der Seiten kann in einem Schritt erfolgen: Math.ceil (x / y)
Alex Moore-Niemis Kommentar als Antwort:
Für Rubyisten hier von Google auf der Suche nach divmod
können Sie es als solches implementieren:
function divmod(x, y) {
var div = Math.trunc(x/y);
var rem = x % y;
return [div, rem];
}
Ergebnis:
// [2, 33]
divmod
Verwendet normalerweise Floored Division ( Math.floor
), was sich von abgeschnittener Division ( Math.trunc
) unterscheidet, wenn negative Zahlen beteiligt sind. Dies gilt auch für das NPM- divmod
Paket , Rubydivmod
, SWI-Prologdivmod
und wahrscheinlich auch für viele andere Implementierungen.
divmod
Fall ist, da es doppelt so schnell ausgeführt wird wie die getrennte Berechnung der beiden Operationen. Das Bereitstellen einer solchen Funktion ohne diesen Leistungsvorteil kann verwirrend sein.
Wenn Sie nur mit Zweierpotenzen teilen, können Sie bitweise Operatoren verwenden:
export function divideBy2(num) {
return [num >> 1, num & 1];
}
export function divideBy4(num) {
return [num >> 2, num & 3];
}
export function divideBy8(num) {
return [num >> 3, num & 7];
}
(Der erste ist der Quotient, der zweite der Rest)
function divideByPowerOf2(num, exponent) { return [num >> exponent, num & ((1 << exponent) - 1)]; }
.
Sie können ternär verwenden, um zu entscheiden, wie auch positive und negative ganzzahlige Werte behandelt werden sollen.
var myInt = (y > 0) ? Math.floor(y/x) : Math.floor(y/x) + 1
Wenn die Zahl positiv ist, ist alles in Ordnung. Wenn die Zahl negativ ist, wird 1 hinzugefügt, da Math.floor mit Negativen umgeht.
Dies wird immer gegen Null abgeschnitten. Ich bin mir nicht sicher, ob es zu spät ist, aber hier ist es:
function intdiv(dividend, divisor) {
divisor = divisor - divisor % 1;
if (divisor == 0) throw new Error("division by zero");
dividend = dividend - dividend % 1;
var rem = dividend % divisor;
return {
remainder: rem,
quotient: (dividend - rem) / divisor
};
}
Wenn Sie den Rest für sehr große Ganzzahlen berechnen müssen, die die JS-Laufzeit nicht als solche darstellen kann (jede Ganzzahl größer als 2 ^ 32 wird als Gleitkomma dargestellt und verliert daher an Genauigkeit), müssen Sie einen Trick ausführen.
Dies ist besonders wichtig, um viele Fälle von Scheckziffern zu überprüfen, die in vielen Fällen unseres täglichen Lebens vorhanden sind (Bankkontonummern, Kreditkarten, ...).
Zunächst benötigen Sie Ihre Nummer als Zeichenfolge (andernfalls haben Sie bereits an Genauigkeit verloren und der Rest macht keinen Sinn).
str = '123456789123456789123456789'
Sie müssen Ihre Zeichenfolge jetzt in kleinere Teile aufteilen, die klein genug sind, damit die Verkettung von Rest und Zeichenfolge in 9 Ziffern passt.
digits = 9 - String(divisor).length
Bereiten Sie einen regulären Ausdruck vor, um die Zeichenfolge zu teilen
splitter = new RegExp(`.{1,${digits}}(?=(.{${digits}})+$)`, 'g')
Wenn zum Beispiel digits
7 ist, ist der reguläre Ausdruck
/.{1,7}(?=(.{7})+$)/g
Es entspricht einer nicht leeren Teilzeichenfolge mit der maximalen Länge 7, auf die (?=...)
eine Anzahl von Zeichen folgt, die ein Vielfaches von 7 ist ( ein positiver Lookahead). Das 'g' soll den Ausdruck durch alle Zeichenfolgen laufen lassen und nicht bei der ersten Übereinstimmung anhalten.
Konvertieren Sie nun jeden Teil in eine Ganzzahl und berechnen Sie die verbleibenden Teile durch reduce
(Addieren des vorherigen Rests - oder 0 - multipliziert mit der korrekten Potenz von 10):
reducer = (rem, piece) => (rem * Math.pow(10, digits) + piece) % divisor
Dies funktioniert aufgrund des Restalgorithmus "Subtraktion":
n mod d = (n - kd) mod d
Dies ermöglicht es, jeden 'Anfangsteil' der Dezimaldarstellung einer Zahl durch den Rest zu ersetzen, ohne den endgültigen Rest zu beeinflussen.
Der endgültige Code würde folgendermaßen aussehen:
function remainder(num, div) {
const digits = 9 - String(div).length;
const splitter = new RegExp(`.{1,${digits}}(?=(.{${digits}})+$)`, 'g');
const mult = Math.pow(10, digits);
const reducer = (rem, piece) => (rem * mult + piece) % div;
return str.match(splitter).map(Number).reduce(reducer, 0);
}
3.5 % 2
1.5. Stellen Sie sicher, dass Sie (parseInt, floor usw.) wie erforderlich behandeln