Zusammenfassung: Die Ganzzahldivision mit Vorzeichen wird gegen Null abgeschnitten . Für nicht negative Ergebnisse entspricht dies dem Boden (rund in Richtung -Infinity). (Beachten Sie, dass C89 dies nicht garantiert, siehe Antworten.)
Peter Cordes
5
Jeder sagt immer wieder "auf Null abschneiden" oder "Decke" oder "Boden", so wie der Code eine bewusste Entscheidung darüber trifft, welche Technik verwendet werden soll. Wenn der Code sprechen könnte, würde er sagen"I just throw the dam fraction part in the trash and move on with life"
Timothy LJ Stewart
3
@ TimothyL.J.Stewart Der "Code" trifft eine bewusste Entscheidung. Gemäß der Spezifikation ist die Ganzzahldivision eine T (Runcation) -Division. Aus diesem Grund wird der Modulo / Rest-Operator anders implementiert als in einer anderen Sprache, z. B. Python oder Ruby. Sehen Sie dies für eine Liste von verschiedenen Möglichkeiten , Sprachen des Modulo - Operator tun und diesem Papier , dass die Listen aus mindestens fünf der gemeinsamen Wegen Programmiersprachen zu tun entscheiden div / Modulo.
13steinj
1
@ 13steinj Ich spreche umgangssprachlich gemäß den Kommentaren, dass es sich in ein "es ist gegen Null abgeschnitten ... nein, es ist Boden ... nein, wenn es negativ ist, seine Decke ..." verwandelt hat. Manchmal verbreiten sich technische Details nicht mit menschlichem Gedächtnis in die Zukunft wie wir es wünschen, aber wenn Sie intuitiv wissen, dass der "Bruchteil weggeworfen wird", können Sie die technischen Punkte ableiten. Die technischen Details sind eine schwere Belastung, aber die Intuition ist leicht und erfrischend wie der Wind. Ich werde sie weit und breit tragen und bei Bedarf wissen, wo ich anfangen soll. Wie das Papier, das Sie verlinkt haben, danke.
Timothy LJ Stewart
Ich antwortete hier mit dem Schwerpunkt auf der euklidischen Division (Zusammenspiel zwischen ganzzahliger Division und Moduloperator).
Picaud Vincent
Antworten:
182
Wird das Ergebnis immer der Boden der Division sein? Was ist das definierte Verhalten?
Ja, ganzzahliger Quotient der beiden Operanden.
6.5.5 Multiplikative Operatoren
6 Wenn ganze Zahlen geteilt werden, ist das Ergebnis des Operators / der algebraische Quotient, wobei jeder Bruchteil verworfen wird. 88) Wenn der Quotient a / b darstellbar ist, ist der Ausdruck (a / b) * b + a% b gleich a.
und die entsprechende Fußnote:
88) Dies wird oft als "Abschneiden gegen Null" bezeichnet.
Natürlich sind zwei Punkte zu beachten:
3 An den Operanden werden die üblichen arithmetischen Konvertierungen durchgeführt.
und:
5 Das Ergebnis des Operators / ist der Quotient aus der Division des ersten Operanden durch den zweiten; Das Ergebnis des Operators% ist der Rest. Wenn in beiden Operationen der Wert des zweiten Operanden Null ist, ist das Verhalten undefiniert.
... es sei denn, Sie teilen natürlich eine negative Zahl durch eine positive (oder vv). In diesem Fall ist dies die Obergrenze.
Will A
74
Es ist weder Boden noch Decke, es ist das Abschneiden eines Bruchteils, es ist konzeptionell anders!
Lornova
38
@ Will A: Nein. Es ist definiert als Abschneiden gegen Null. Wenn Sie es anders nennen, wird dies nur zu Verwirrung führen. Bitte unterlassen Sie dies.
Martin York
43
Zumindest aus mathematischer Sicht entspricht das Abschneiden gegen Null "wenn> 0, dann Boden sonst Decke". Ich denke, es einfach zu nennen ist einfacher als es Boden / Decke zu nennen, aber beides ist gültig. Unabhängig davon ist der Punkt von Will A gültig: Dirkgentlys Antwort ist teilweise falsch, da er erklärte, dass das OP Recht hat, wenn das Ergebnis das Stockwerk der Division ist.
Brian
9
@Philip Potter: Ich glaube nicht, dass es in C89 definiert wurde, und es ist nicht im C ++ - Standard von 1998. In diesen musste natürlich (a / b) * b + a % b == abefriedigt werden, und der absolute Wert von a % bmusste kleiner sein als a, aber ob a % bnegativ für negativ war aoder bnicht angegeben wurde.
David Thornley
39
Dirkgently gibt eine hervorragende Beschreibung der Ganzzahldivision in C99, aber Sie sollten auch wissen, dass in C89 die Ganzzahldivision mit einem negativen Operanden eine implementierungsdefinierte Richtung hat.
Aus dem ANSI C-Entwurf (3.3.5):
Wenn einer der Operanden negativ ist, wird die Implementierung definiert, ob das Ergebnis des Operators / die größte Ganzzahl ist, die kleiner als der algebraische Quotient ist, oder die kleinste Ganzzahl, die größer als der algebraische Quotient ist, ebenso wie das Vorzeichen des Ergebnisses des Operators%. Wenn der Quotient a / b darstellbar ist, ist der Ausdruck (a / b) * b + a% b gleich a.
Achten Sie also auf negative Zahlen, wenn Sie mit einem C89-Compiler nicht weiterkommen.
Es ist eine lustige Tatsache, dass C99 die Kürzung gegen Null gewählt hat, weil FORTRAN das so gemacht hat. Siehe diese Nachricht auf comp.std.c.
In C99-Entwurf N1256, Vorwort, Absatz 5, wird reliable integer divisioneine neue Sprachfunktion erwähnt . Erstaunlich *-*.
Ciro Santilli 法轮功 冠状 病 六四 事件 11
Beim Abschneiden verhält sich die gängigste CPU-Hardware (z. B. x86). Es wäre also verrückt, eine andere Wahl zu treffen. IDK, das zuerst kam, Fortran-Semantik oder Hardware-Verhalten, aber es ist kein Zufall, dass diese auch gleich sind.
Peter Cordes
2
@PeterCordes: Die meisten gängigen CPU-Geräte können die Teilung auf dem Boden durch die meisten Konstanten schneller durchführen als die Teilung. Meiner Meinung nach wäre es besser gewesen, wenn der Standard dies gesagt hätte expr1 / expr2und expr1 % expr2miteinander konsistent sein müsste, wenn beide Instanzen expr1dieselben Objekte auf dieselbe Weise und ebenfalls für kombinieren expr2, aber die Wahl zwischen Abschneiden und Aufteilen auf dem Boden ist ansonsten nicht spezifiziert. Das hätte eine effizientere Codegenerierung ermöglicht, ohne die Kompatibilität zu
beeinträchtigen
23
Wenn das Ergebnis negativ ist, schneidet C eher auf 0 als auf den Boden ab. Ich habe in dieser Lektüre erfahren, warum die Python-Ganzzahldivision hier immer Stockwerke bildet: Warum Pythons Ganzzahldivisionsetagen
Ich stimme dem Kommentar zu und frage mich, ob es jemals sinnvoll ist, (neg% pos) negativ zu werden. In diesem Zusammenhang frage ich mich, ob das erforderliche arithmetisch inkorrekte Verhalten in einigen Fällen von "unsignedvar >ignedvar" jemals nützlich ist. Ich kann die Gründe verstehen, warum nicht immer korrektes Verhalten erforderlich ist. Ich sehe keine Gründe dafür, falsches Verhalten zu fordern.
Supercat
8
+1 für eine hervorragende Referenz, warum Bodenbeläge das richtige Verhalten für die Ganzzahldivision sind (entgegen der Definition von C, die gebrochen und fast nie nützlich ist).
R .. GitHub STOP HELPING ICE
@supercat Betrachten Sie : filtered = (k - 1) * filtered + value + carry; carry = filtered % factor; filtered /= factor, iteriert mit sich ändernden Werten von value. Es ist eine schöne ganzzahlige Annäherung an ein Tiefpassfilter erster Ordnung mit Zeitkonstante k... aber es ist nur symmetrisch, wenn die Division abgeschnitten wird und carrynegative Werte erhält. Beide Verhaltensweisen für die Teilung sind von Zeit zu Zeit nützlich.
Hobbs
1
@hobbs: Ich glaube nicht, dass sich der obige Code sauber verhält, wenn Signale Null überschreiten. Wenn dives sich um einen Bodenteilungsoperator handelt und factorungerade ist, filtered += (filter+(factor div 2)) div factorwürde dies für alle Werte bis zu einem sauberen und symmetrischen Verhalten ergeben INT_MAX-(factor div 2).
Supercat
@supercat es funktioniert aber; Dieser Code ist nur geringfügig von etwas destilliert, das ich eine Weile in der Steuerung einer Atomuhr ausgeführt habe.
Hobbs
21
Ja, das Ergebnis wird immer gegen Null abgeschnitten. Es wird auf den kleinsten absoluten Wert gerundet.
-5/2=-25/2=2
Für vorzeichenlose und nicht negativ vorzeichenbehaftete Werte entspricht dies dem Boden (Rundung in Richtung -Infinity).
"I just throw the dam fraction part in the trash and move on with life"
Antworten:
Ja, ganzzahliger Quotient der beiden Operanden.
und die entsprechende Fußnote:
Natürlich sind zwei Punkte zu beachten:
und:
[Anmerkung: Hervorhebung von mir]
quelle
(a / b) * b + a % b == a
befriedigt werden, und der absolute Wert vona % b
musste kleiner sein alsa
, aber oba % b
negativ für negativ wara
oderb
nicht angegeben wurde.Dirkgently gibt eine hervorragende Beschreibung der Ganzzahldivision in C99, aber Sie sollten auch wissen, dass in C89 die Ganzzahldivision mit einem negativen Operanden eine implementierungsdefinierte Richtung hat.
Aus dem ANSI C-Entwurf (3.3.5):
Achten Sie also auf negative Zahlen, wenn Sie mit einem C89-Compiler nicht weiterkommen.
Es ist eine lustige Tatsache, dass C99 die Kürzung gegen Null gewählt hat, weil FORTRAN das so gemacht hat. Siehe diese Nachricht auf comp.std.c.
quelle
reliable integer division
eine neue Sprachfunktion erwähnt . Erstaunlich*-*
.expr1 / expr2
undexpr1 % expr2
miteinander konsistent sein müsste, wenn beide Instanzenexpr1
dieselben Objekte auf dieselbe Weise und ebenfalls für kombinierenexpr2
, aber die Wahl zwischen Abschneiden und Aufteilen auf dem Boden ist ansonsten nicht spezifiziert. Das hätte eine effizientere Codegenerierung ermöglicht, ohne die Kompatibilität zuWenn das Ergebnis negativ ist, schneidet C eher auf 0 als auf den Boden ab. Ich habe in dieser Lektüre erfahren, warum die Python-Ganzzahldivision hier immer Stockwerke bildet: Warum Pythons Ganzzahldivisionsetagen
quelle
filtered = (k - 1) * filtered + value + carry; carry = filtered % factor; filtered /= factor
, iteriert mit sich ändernden Werten vonvalue
. Es ist eine schöne ganzzahlige Annäherung an ein Tiefpassfilter erster Ordnung mit Zeitkonstantek
... aber es ist nur symmetrisch, wenn die Division abgeschnitten wird undcarry
negative Werte erhält. Beide Verhaltensweisen für die Teilung sind von Zeit zu Zeit nützlich.div
es sich um einen Bodenteilungsoperator handelt undfactor
ungerade ist,filtered += (filter+(factor div 2)) div factor
würde dies für alle Werte bis zu einem sauberen und symmetrischen Verhalten ergebenINT_MAX-(factor div 2)
.Ja, das Ergebnis wird immer gegen Null abgeschnitten. Es wird auf den kleinsten absoluten Wert gerundet.
Für vorzeichenlose und nicht negativ vorzeichenbehaftete Werte entspricht dies dem Boden (Rundung in Richtung -Infinity).
quelle
Nein. Das Ergebnis variiert, aber die Variation tritt nur bei negativen Werten auf.
Um es klar zu machen, rundet der Boden in Richtung negativer Unendlichkeit, während die ganzzahlige Division in Richtung Null rundet (abgeschnitten).
Für positive Werte sind sie gleich
Bei negativem Wert ist dies anders
quelle
Ich weiß, dass die Leute Ihre Frage beantwortet haben, aber in Laienbegriffen:
5 / 2 = 2
// da sowohl 5 als auch 2 ganze Zahlen sind und die Ganzzahldivision immer Dezimalstellen abschneidet5.0 / 2 or 5 / 2.0 or 5.0 /2.0 = 2.5
// hier hat entweder 5 oder 2 oder beide eine Dezimalzahl, daher ist der Quotient, den Sie erhalten, dezimal.quelle