Warum funktioniert die Moduldivision (%) nur mit ganzen Zahlen?

Lesezeit: 7 Minuten

Warum funktioniert die Moduldivision nur mit ganzen Zahlen
Brenda Lang

Ich bin kürzlich auf ein Problem gestoßen, das leicht mit der Moduldivision gelöst werden konnte, aber die Eingabe war ein Float:

Bei einer periodischen Funktion (z sin) und eine Computerfunktion, die es nur innerhalb des Periodenbereichs berechnen kann (z [-π, π]), erstellen Sie eine Funktion, die jede Eingabe verarbeiten kann.

Die “offensichtliche” Lösung ist so etwas wie:

#include <cmath>

float sin(float x){
    return limited_sin((x + M_PI) % (2 *M_PI) - M_PI);
}

Warum funktioniert das nicht? Ich bekomme diesen Fehler:

error: invalid operands of types double and double to binary operator %

Interessanterweise funktioniert es in Python:

def sin(x):
    return limited_sin((x + math.pi) % (2 * math.pi) - math.pi)

  • π ist nicht gleich 3,14 und kann tatsächlich nicht als Fließkommatyp dargestellt werden. Rechnen sin(x) für große Werte von x erfordert tatsächlich einen sehr schwierigen transzendentalen Argumentreduktionsprozess, der mit keiner endlichen Annäherung an pi auskommt.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    23. Mai 2011 um 21:03 Uhr

  • Dies ist mit ziemlicher Sicherheit eine Hausaufgabe, sodass Fließkommafehler entweder außerhalb des Aufgabenbereichs liegen oder zu einer Diskussion über eine strengere numerische Analyse führen sollen. So oder so, fmod ist wahrscheinlich das, wonach der Ausbilder sucht.

    – Dennis Zickefoose

    23. Mai 2011 um 21:16 Uhr

  • Es ist keine Hausaufgabe, es ist nur etwas, das beim Lesen einer anderen SO-Frage aufgetaucht ist (stackoverflow.com/questions/6091837/…)

    – Brendan Lange

    23. Mai 2011 um 22:10 Uhr

  • OK, ich hätte meine Aussage präziser machen sollen. Mein Punkt war, dass, wenn das Argument unbegrenzt groß werden kann (nicht nur die Exponentengröße mit doppelter Genauigkeit), keine endliche Annäherung an pi ausreicht. Für Double, ja, wird eine sehr, sehr lange Annäherung an Pi ausreichen.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    15. Juli 2012 um 0:21 Uhr

  • @aschepler: Ich glaube nicht, dass du das Problem verstanden hast.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    10. Juli 2013 um 1:30 Uhr

1647057010 892 Warum funktioniert die Moduldivision nur mit ganzen Zahlen
Ameise

Weil der normale mathematische Begriff „Rest“ nur auf die ganzzahlige Division anwendbar ist. dh Division, die erforderlich ist, um einen ganzzahligen Quotienten zu erzeugen.

Um das Konzept des “Rests” auf reelle Zahlen auszudehnen, müssen Sie eine neue Art von “Hybrid”-Operation einführen, die erzeugen würde ganze Zahl Quotient für Real Operanden. Die Core-C-Sprache unterstützt eine solche Operation nicht, wird aber als Standardbibliothek bereitgestellt fmod Funktion sowie remainder Funktion in C99. (Beachten Sie, dass diese Funktionen nicht identisch sind und einige Besonderheiten aufweisen. Insbesondere folgen sie nicht den Rundungsregeln der ganzzahligen Division.)

  • Von Wert aus der Definition von % im 98er Standard: “(a/b)*b + a%b ist gleich a.” Für Fließkommatypen gilt: (a/b)*b schon gleich a [insofar as such a statement can be made for floating point types]damit a%b wäre nie besonders nützlich.

    – Dennis Zickefoose

    23. Mai 2011 um 21:10 Uhr

  • @Dennis: In der Tat ist der Rest in einem Feld algebraisch immer 0. Die am besten geeignete Definition von % Operator für Fließkomma, nehme ich an, wäre a-(a/b)*bwas entweder 0 oder ein sehr kleiner Wert wäre.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    23. Mai 2011 um 21:17 Uhr

  • @Dennis: Sie können diese Formel leicht korrigieren, indem Sie “floor(a/b)*b + a%b = a” verlangen. Beachten Sie, dass für ganze Zahlen floor(a/b) = a/b ist.

    – Vog

    23. Mai 2011 um 21:22 Uhr

  • Die ganzzahlige Division im C-Stil verwendet Trunc, nicht Floor, aber der Punkt bleibt.

    – dan04

    10. Juli 2013 um 2:23 Uhr

  • -1 Bezüglich „der normale mathematische Begriff des „Rests“ ist nur auf die ganzzahlige Division anwendbar“, funktioniert der mathematische Begriff der Modulo-Arithmetik auch für Gleitkommawerte, und dies ist eines der ersten Probleme, die Donald Knuth in seinem Klassiker behandelt Die Kunst der Computerprogrammierung (Band I). Dh es war einmal Grundwissen. Heutzutage erhalten Studenten meiner Meinung nach nicht die Ausbildung, für die sie bezahlen.

    – Prost und hth. – Alf

    23. August 2014 um 10:51 Uhr


1647057010 359 Warum funktioniert die Moduldivision nur mit ganzen Zahlen
Doug Stephen

Du schaust nach fmod().

Ich denke, um Ihre Frage genauer zu beantworten, in älteren Sprachen die % Operator wurde nur als ganzzahlige modulare Division definiert und in neueren Sprachen haben sie beschlossen, die Definition des Operators zu erweitern.

BEARBEITEN: Wenn ich raten müsste, warum, würde ich sagen, weil die Idee der modularen Arithmetik aus der Zahlentheorie stammt und sich speziell mit ganzen Zahlen befasst.

  • “ältere Sprachen” – APL stammt aus den 1960er Jahren und sein Modulo-Operator “|” arbeitet sowohl mit Ganzzahlen als auch mit Fließkommadaten (auch mit Skalar, Vektor, Matrix, Tensor, …) . Es gibt keinen guten Grund, warum der Modulo-Operator “%” von C nicht dieselbe Funktion wie fmod hätte ausführen können, wenn er mit Gleitkommazahlen verwendet worden wäre.

    – rcgldr

    23. August 2014 um 1:16 Uhr


  • @rcgldr Die Designziele erforderten kein Gleitkomma-Modulo. C wurde implementiert, um Unix zu kompilieren und die Menge an Assemblersprache zu begrenzen, die für das Betriebssystem benötigt wird. „C ist eine imperative prozedurale Sprache. Sie wurde entwickelt, um mit einem relativ unkomplizierten Compiler kompiliert zu werden, Low-Level-Zugriff auf den Speicher bereitzustellen, Sprachkonstrukte bereitzustellen, die Maschinenanweisungen effizient zuordnen, und minimale Laufzeitunterstützung zu erfordern.“ en.wikipedia.org/wiki/C_(Programmiersprache)

    – Harfner

    8. Februar 2019 um 8:52 Uhr

  • @harper – Da C Gleitkomma-Arithmetik wie Addieren, Subtrahieren, Multiplizieren und Dividieren mit derselben Syntax wie für ganze Zahlen enthält, verstehe ich nicht, warum es nicht auch Modulo mit derselben Syntax hätte enthalten können (%) . Die Entscheidung, es aufzunehmen oder nicht, erscheint willkürlich.

    – rcgldr

    8. Februar 2019 um 9:28 Uhr

Ich kann es nicht wirklich sagen sicher, aber ich denke, es ist hauptsächlich historisch. Nicht wenige frühe C-Compiler unterstützten Gleitkommazahlen überhaupt nicht. Es wurde später hinzugefügt, und selbst dann nicht so vollständig – hauptsächlich wurde der Datentyp hinzugefügt, und die die meisten Primitive Operationen werden in der Sprache unterstützt, aber alles andere bleibt der Standardbibliothek überlassen.

  • +1 für die erste vernünftige Antwort, die ich sehe, wenn ich die Liste durchlese. Eigentlich, nachdem ich sie jetzt alle gelesen habe, ist dies der nur vernünftige Antwort.

    – Prost und hth. – Alf

    23. August 2014 um 10:54 Uhr


  • Auch von mir ein verspätetes +1. Früher habe ich in C für 6809- und Z80-Embedded-Systeme geschrieben. Auf keinen Fall konnte ich mir den Platz leisten, um die c-Laufzeitbibliothek einzuschließen. Ich musste sogar meinen eigenen Startcode schreiben. Floating Point war ein Luxus, den ich mir nicht leisten konnte 🙂

    – Richard Hodges

    2. Januar 2016 um 15:44 Uhr

Der Modulo-Operator % in C und C++ ist für zwei ganze Zahlen definiert, es gibt jedoch eine fmod() Funktion für die Verwendung mit Doubles verfügbar.

Warum funktioniert die Moduldivision nur mit ganzen Zahlen
Yu Hao

Die Einschränkungen sind in den Standards:

C11 (ISO/IEC 9899:201x) §6.5.5 Multiplikative Operatoren

Jeder der Operanden muss vom arithmetischen Typ sein. Die Operanden des %-Operators müssen vom Typ Integer sein.

C++11 (ISO/IEC 14882:2011) §5.6 Multiplikative Operatoren

Die Operanden von * und / müssen vom arithmetischen oder Aufzählungstyp sein; die Operanden von % müssen vom Typ Ganzzahl oder Aufzählung sein. Die üblichen arithmetischen Konvertierungen werden an den Operanden durchgeführt und bestimmen die Art des Ergebnisses.

Die Lösung ist zu verwenden fmodweshalb die Operanden von % sind in erster Linie auf Integer-Typen beschränkt, gemäß C99 Begründung §6.5.5 Multiplikative Operatoren:

Das C89-Komitee lehnte die Ausweitung des %-Operators auf die Arbeit mit schwimmenden Typen ab, da eine solche Verwendung die von fmod bereitgestellte Einrichtung duplizieren würde

1647057011 573 Warum funktioniert die Moduldivision nur mit ganzen Zahlen
Oliver Charlesworth

Versuchen fmod

Warum funktioniert die Moduldivision nur mit ganzen Zahlen
Andreas

Der %-Operator gibt Ihnen einen REST (ein anderer Name für Modulus) einer Zahl. Für C/C++ ist dies nur für Integer-Operationen definiert. Python ist etwas breiter und ermöglicht es Ihnen, den Rest einer Gleitkommazahl für den Rest zu erhalten, wie oft die Zahl darin geteilt werden kann:

>>> 4 % math.pi
0.85840734641020688
>>> 4 - math.pi
0.85840734641020688
>>> 

  • Rest ist nicht ‘anderer Name für Modul’ !! Siehe: stackoverflow.com/questions/13683563/… oder aus einem Mathe-Pov: math.stackexchange.com/questions/801962/… Einfach ausgedrückt: Modulo und Rest sind nur Dasselbe gilt für positive Zahlen, und ein weiteres Beispiel ist, dass der Rest Sie nicht um den Kompass herumgehen lässt (gegen den Uhrzeigersinn). Bitte korrigieren Sie das, da ich zu sparsam bin, um abzustimmen :P

    – GitaarLAB

    21. März 2016 um 21:31 Uhr

992600cookie-checkWarum funktioniert die Moduldivision (%) nur mit ganzen Zahlen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy