Warum wird das Divisionsergebnis zwischen zwei Ganzzahlen abgeschnitten?

7

Alle erfahrenen Programmierer in C # (ich denke, das kommt von C) werden verwendet, um die Ganzzahlen in einer Division zu aktivieren, um das Dezimal / Doppel / Float-Ergebnis anstelle von int (das tatsächliche Ergebnis abgeschnitten) zu erhalten.

Ich würde gerne wissen, warum das so umgesetzt wird? Gibt es einen guten Grund, das Ergebnis zu kürzen, wenn beide Zahlen Integer sind?

    
Diego 23.03.2012, 14:52
quelle

6 Antworten

12

C # verfolgt sein Erbe in C, also die Antwort auf "Warum ist es in C # so?" ist eine Kombination von "warum ist es so in C?" und "gab es keinen guten Grund, sich zu ändern?"

Der Ansatz von C besteht darin, eine ziemlich enge Übereinstimmung zwischen der Hochsprachen- und der Low-Level-Operation zu erreichen. Prozessoren implementieren im Allgemeinen ganzzahlige Division als zurückkehrenden einen Quotienten und einen Rest, die beide von dem gleichen Typ wie die Operanden sind.

(Meine Frage wäre also: "Warum gibt Integer-Division in C-ähnlichen Sprachen nicht zwei ganze Zahlen " zurück, nicht "warum gibt es keinen Gleitkommawert zurück?")

Die Lösung bestand darin, separate Operationen für Division und Rest bereitzustellen, von denen jede eine ganze Zahl zurückgibt. Im Zusammenhang mit C ist es nicht verwunderlich, dass das Ergebnis jeder dieser Operationen eine ganze Zahl ist. Dies ist häufig genauer als Fließkomma-Arithmetik. Betrachten Sie das Beispiel aus Ihrem Kommentar von 7 / 3 . Dieser Wert kann nicht durch eine endliche Binärzahl noch durch eine endliche Dezimalzahl dargestellt werden. Mit anderen Worten, können wir 7 / 3 nicht genau darstellen, es sei denn verwenden wir ganze Zahlen! Die genaueste Darstellung dieses Bruchteils ist "Quotient 2, Rest 1".

Also, gab es keinen guten Grund, sich zu ändern? Ich kann mir keine vorstellen, und ich kann mir ein paar gute Gründe überlegen, sie zu ändern. Keine der anderen Antworten hat Visual Basic erwähnt, das (zumindest bis Version 6) zwei Operatoren zum Dividieren von ganzen Zahlen hat: / konvertiert die ganzen Zahlen zu double und gibt ein double zurück, während \ normale Ganzzahlarithmetik ausführt.

Ich habe über den Operator \ erfahren, nachdem ich versucht hatte, einen binären Suchalgorithmus mit Gleitkomma-Division zu implementieren. Es war wirklich schmerzhaft, und die Integer-Division kam wie ein Hauch frischer Luft herein. Ohne es gab es viele spezielle Handhabung, um Randfälle und Fehler in der ersten Version des Verfahrens zu decken.

Aus dieser Erfahrung ziehe ich die Schlussfolgerung, dass verschiedene Operatoren zum Teilen ganzer Zahlen verwirrend sind.

Eine andere Alternative wäre, nur eine Integer-Operation zu haben, die immer ein Double liefert, und Programmierer müssen sie abschneiden. Das bedeutet, dass Sie jedes Mal, wenn Sie eine Integer-Division wünschen, zwei int- & gt; doppelte Konvertierungen, eine Trunkierung und eine doppelte & gt; int-Konvertierung durchführen müssen. Und wie viele Programmierer würden irrtümlich das Ergebnis runden oder überlagern, anstatt es zu kürzen? Es ist ein komplizierteres System und mindestens so anfällig für Programmierer Fehler und langsamer.

Zusätzlich zur binären Suche gibt es viele Standardalgorithmen, die ganzzahlige Arithmetik verwenden. Ein Beispiel ist das Aufteilen von Sammlungen von Objekten in Untersammlungen ähnlicher Größe. Ein anderer wandelt zwischen Indizes in einem 1-d-Array und Koordinaten in einer 2-d-Matrix um.

Soweit ich sehen kann, überlebt keine Alternative zu "int / int yields int" eine Kosten-Nutzen-Analyse in Bezug auf die Sprachverwendbarkeit, so dass es keinen Grund gibt, das von C. geerbte Verhalten zu ändern.

Fazit:

  • Integer-Division ist häufig in vielen Standardalgorithmen nützlich.
  • Wenn die Gleitkommadivision von ganzen Zahlen benötigt wird, kann sie explizit mit einer einfachen, kurzen und klaren Umwandlung aufgerufen werden: (double)a / b anstatt a / b
  • Andere Alternativen führen zu mehr Komplikationen sowohl für den Programmierer als auch für mehr Taktzyklen für den Prozessor.
phoog 23.03.2012, 20:17
quelle
12
  

Gibt es einen guten Grund, das Ergebnis zu kürzen, wenn beide Zahlen Integer sind?

Natürlich; Ich kann mir ein Dutzend solcher Szenarien leicht vorstellen. Beispiel: Sie haben ein großes Bild und eine Miniaturansicht des Bildes, die in beiden Dimensionen 10 Mal kleiner ist. Wenn der Benutzer auf einen Punkt in dem großen Bild klickt, möchten Sie das entsprechende Pixel in dem verkleinerten Bild identifizieren. Um dies zu tun, teilen Sie die x- und y-Koordinaten durch 10. Warum möchten Sie ein Ergebnis in Dezimal erhalten? Die entsprechenden Koordinaten werden ganzzahlige Koordinaten in der Miniaturbild-Bitmap sein.

Doppelte Zahlen sind ideal für physikalische Berechnungen und Dezimalzahlen sind ideal für finanzielle Berechnungen, aber fast die ganze Arbeit, die ich mit Computern mache, die irgendeine Mathematik überhaupt tut, macht sie vollständig in ganzen Zahlen. Ich möchte nicht ständig Doppel- oder Dezimalzahlen in ganze Zahlen umwandeln, nur weil ich eine Division gemacht habe. Wenn Sie physikalische oder finanzielle Probleme lösen, dann Warum verwenden Sie Integer überhaupt? Verwenden Sie nothing , aber doubles oder decimal. Verwenden Sie Ganzzahlen, um endliche Mathematikprobleme zu lösen.

    
Eric Lippert 23.03.2012 15:32
quelle
10

Das Berechnen von ganzen Zahlen ist schneller (normalerweise) als bei Gleitkommawerten. Außerdem geben alle anderen Integer / Integer-Operationen ( + , - , * ) eine ganze Zahl zurück.

BEARBEITEN: Gemäß der Anfrage des OP, hier ist eine Ergänzung:

Das OP-Problem ist, dass sie an / als Division im mathematischen Sinn denken und der / Operator in der Sprache eine andere Operation ausführt (was nicht die mathematische Division ist). Mit dieser Logik sollten sie auch die Gültigkeit aller anderen Operationen ( + , - , * ) in Frage stellen, da diese spezielle Überlaufregeln haben, die nicht mit ihren mathematischen Gegenstücken übereinstimmen. Wenn dies für jemanden unangenehm ist, sollten sie eine andere Sprache finden, in der die Operationen wie von der Person erwartet ausgeführt werden.

Was den Anspruch auf Leistungsdifferenz zugunsten ganzzahliger Werte anbelangt: Als ich die Antwort schrieb, hatte ich nur "Folkwissen" und "Intuition", um die Behauptung zu stützen (hece mein "gewöhnlich" Disclaimer). In der Tat gab es, wie Gabe ausführte, Plattformen, wo dies nicht gilt. Auf der anderen Seite fand ich diesen Link (Punkt 12), der gemischte Leistungen auf einer Intel-Plattform zeigt (die verwendete Sprache ist Java (obwohl).

Das Mitnehmen sollte sein, dass mit der Leistung viele Behauptungen und Intuitionen unbegründet sind, bis sie gemessen und für wahr gehalten werden.

    
Attila 23.03.2012 14:55
quelle
2

Ja, wenn das Endergebnis eine ganze Zahl sein soll. Es hängt von den Anforderungen ab.

Wenn dies tatsächlich Ihre Anforderungen sind, sollten Sie keine Dezimalzahl speichern und sie dann abschneiden. Sie würden Speicher- und Verarbeitungszeit verschwenden, um etwas zu erreichen, das bereits eingebaute Funktionalität ist.

    
Justin Pihony 23.03.2012 14:53
quelle
2

Der Operator soll den gleichen Typ wie die Eingabe zurückgeben.

Bearbeiten (Kommentarantwort): Warum? Ich entwerfe keine Sprachen, aber ich würde meistens davon ausgehen, dass Sie mit den Datentypen, mit denen Sie begonnen haben, und in der verbleibenden Instanz weitermachen. Mit welchen Kriterien würden Sie automatisch davon ausgehen, welchen Typ der Benutzer möchte? Würden Sie automatisch eine Zeichenfolge erwarten, wenn Sie sie brauchen? (Aufrichtigkeit beabsichtigt)

    
John MacIntyre 23.03.2012 14:57
quelle
1

Wenn Sie einem int einen int hinzufügen, erwarten Sie einen int. Wenn Sie ein int von einem int subtrahieren, erwarten Sie einen int. Wenn Sie ein int mit einem int multiplizieren, erwarten Sie einen int. Warum also würden Sie kein int-Ergebnis erwarten, wenn Sie ein int durch ein int teilen? Und wenn Sie ein int erwarten, müssen Sie abschneiden.

Wenn Sie das nicht wollen, müssen Sie Ihre Eingaben zuerst auf etwas anderes anwenden.

Edit: Ich würde auch bemerken, dass, wenn Sie wirklich verstehen wollen, warum das ist, dann sollten Sie anfangen zu untersuchen, wie binäre Mathematik funktioniert und wie es in einer elektronischen Schaltung implementiert ist. Es ist sicherlich nicht notwendig, es im Detail zu verstehen, aber ein schneller Überblick darüber würde Ihnen wirklich helfen, zu verstehen, wie sich die Low-Level-Details der Hardware bis hin zu den Details der Hochsprachen durchschauen.

    
Matt Burland 23.03.2012 14:56
quelle

Tags und Links