it-swarm.com.de

Ganzzahlige Division mit Rest in JavaScript?

Wie bekomme ich in JavaScript:

  1. die ganze Anzahl, wie oft eine gegebene ganze Zahl in eine andere geht?
  2. der rest?
762
Yarin

Für eine Zahl y und einen Divisor x berechnen Sie den Quotienten (quotient) und den Rest (remainder) als:

var quotient = Math.floor(y/x);
var remainder = y % x;
1016
Mark Elliot

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 rundet.

Das scheint auch richtig zu sein:

var num = (a / b) >> 0;
331
user113716

Ich habe einige Geschwindigkeitstests mit Firefox gemacht.

-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 oben genannte basiert auf jeweils 10 Millionen Versuchen.

Schlussfolgerung: Verwenden Sie (a/b>>0) (oder (~~(a/b)) oder (a/b|0)), um eine Effizienzsteigerung von ca. 20% zu erzielen. Denken Sie auch daran, dass sie mit Math.floor nicht übereinstimmen, wenn a/b<0 && a%b!=0.

170
KalEl

ES6 führt die neue Methode Math.trunc ein. Dies ermöglicht es, @ MarkElliots Antwort zu korrigieren, damit es 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 arbeiten31.

105
Oriol
var remainder = x % y;
return (x - remainder) / y;
21
gammax

Sie können die Funktion parseInt verwenden, um ein abgeschnittenes Ergebnis zu erhalten.

parseInt(a/b)

Um einen Rest zu erhalten, verwenden Sie den Mod-Operator:

a%b

parseInt hat einige Fallstricke mit Strings, um die Verwendung des Radix-Parameters mit der 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 liefert 1 als Ergebnis.

JavaScript berechnet die Untergrenze der negativen Zahlen und den Rest der nicht ganzzahligen Zahlen nach den mathematischen Definitionen.

FLOOR ist definiert als "die größte ganze Zahl, die kleiner als der Parameter ist", also:

  • positive Zahlen: FLOOR (X) = ganzzahliger Teil von X;
  • negative Zahlen: FLOOR (X) = ganzzahliger Teil von X minus 1 (weil es KLEINER sein muss als der Parameter, d. h. negativer!)

REMAINDER ist definiert als "Rest" einer Division (Euklidische Arithmetik). Wenn der Dividend keine ganze Zahl ist, ist der Quotient normalerweise auch keine ganze Zahl, dh es gibt keinen Rest, sondern wenn der Quotient gezwungen ist, eine ganze Zahl zu sein (und dies ist der Fall, wenn jemand versucht, den Rest oder das Modul von a zu erhalten Fließkommazahl), wird natürlich eine nicht ganzzahlige Zahl übrig bleiben.

JavaScript berechnet alles wie erwartet, daher muss der Programmierer darauf achten, die richtigen Fragen zu stellen (und die Leute sollten darauf achten, das zu beantworten, was gefragt wird!) Yarins erste Frage war NICHT "Was ist die Ganzzahl-Division von X durch Y", sondern stattdessen "die ganze Anzahl, wie oft eine gegebene ganze Zahl in eine andere geht". Bei positiven Zahlen ist die Antwort für beide gleich, nicht jedoch für negative Zahlen, da die Ganzzahldivision (Dividende nach Divisor) -1 kleiner ist als die Anzahl, zu der eine Zahl (Divisor) in eine andere (Dividende) geht. 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 hat richtig geantwortet, dieser Code funktioniert wie von Yarin gefordert. Auf der anderen Seite ist Samuel falsch, er hat nicht die Mathematik gemacht, oder er hätte gesehen, dass es funktioniert (auch, er hat nicht gesagt, was der Teiler seines Beispiels war, aber ich hoffe, dass es so war 3):

Rest = X% Y = -100% 3 = -1

GoesInto = (X - Rest)/Y = (-100 - -1)/3 = -99/3 = -33

Ich habe den Code übrigens auf Firefox 27.0.1 getestet. Er funktionierte wie erwartet mit positiven und negativen Zahlen sowie mit nicht ganzzahligen Werten, sowohl für Dividende als auch für Divisor. Beispiel:

-100.34/3.57: GoesInto = -28, Rest = -0.3800000000000079

Ja, ich habe bemerkt, dass ein Präzisionsproblem vorliegt, aber ich hatte keine Zeit, um es zu überprüfen (ich weiß nicht, ob es ein Problem mit Firefox, Windows 7 oder der CPU-CPU meiner CPU ist). Für Yarins Frage, die nur ganze Zahlen beinhaltet, funktioniert der gammax-Code jedoch einwandfrei.

6
Cyberknight

Math.floor(operation) gibt den abgerundeten Wert der Operation zurück.

Beispiel von 1st Frage:

var x = 5;
var y = 10.4;
var z = Math.floor(x + y);

console.log(z);

Konsole:

fünfzehn

Beispiel von 2nd Frage:

var x = 14;
var y = 5;
var z = Math.floor(x%y);

console.log(x);

Konsole:

4

5
Aetricity

Kommentar von Alex Moore-Niemi als Antwort:

Für Rubyisten hier bei Google auf der Suche nach divmod können Sie es so implementieren: 

function divmod(x, y) {
  var div = Math.trunc(x/y);
  var rem = x % y;
  return [div, rem];
}

Ergebnis:

// [2, 33]
2
Alex

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)

1

Die Anzahl der Seiten kann in einem Schritt berechnet werden: Math.ceil (x/y)

1
user1920925

Sie können ternary verwenden, um zu entscheiden, wie auch positive und negative Ganzzahlwerte 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.

0
John Galt

Dies wird immer gegen Null abschneiden. Nicht sicher, ob es zu spät ist, aber hier geht 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
    };
}
0
bzim

Ich benutze normalerweise (a - a % b) / b. Es ist wahrscheinlich nicht das eleganteste, aber es funktioniert.

0
Wolf Elkan

Wenn Sie den Rest für sehr große Ganzzahlen berechnen müssen, die von der JS-Laufzeit nicht als solche dargestellt werden können (jede Ganzzahl größer als 2 ^ 32 wird als Float dargestellt und verliert an Präzision), müssen Sie einige Tricks ausführen.

Dies ist besonders wichtig für die Überprüfung vieler Fälle von Prüfziffern, die in vielen Fällen unseres täglichen Lebens vorhanden sind (Bankkontonummern, Kreditkarten usw.).

Zunächst benötigen Sie Ihre Nummer als Zeichenkette (sonst haben Sie bereits an Genauigkeit verloren und der Rest macht keinen Sinn).

str = '123456789123456789123456789'

Jetzt müssen Sie Ihre Zeichenfolge in kleinere Teile aufteilen, die klein genug sind, damit die Verkettung von Rest und ein Stück Schnur 9-stellig passen kann.

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, lautet der Regexp

/.{1,7}(?=(.{7})+$)/g

Er stimmt mit einem nicht-leeren Teilstring mit maximaler Länge 7 überein, auf den ((?=...) ist ein positiver Lookahead) eine Anzahl von Zeichen folgt, die ein Vielfaches von 7 ist. Das 'g' bewirkt, dass der Ausdruck alle Zeichenfolgen durchläuft und nicht beim ersten Treffer aufhört .

Wandle nun jeden Teil in eine Ganzzahl um und berechne die Reste mit reduce (addiere den vorherigen Rest - oder 0 - multipliziert mit der richtigen 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);
}
0
rewritten