Ich bin kürzlich auf ein Problem gestoßen, das mit der Modulteilung leicht gelöst werden konnte, aber die Eingabe war ein Float:
Erstellen Sie mit einer periodischen Funktion (z. B.
sin
) und einer Computerfunktion, die sie nur innerhalb des Periodenbereichs berechnen kann (z. B. [-π, π]), 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 erhalte 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)
sin(x)
großer Werte vonx
erfordert tatsächlich einen sehr schwierigen Prozess zur Reduzierung transzendentaler Argumente, der mit keiner endlichen Näherung von pi auskommt.fmod
ist es wahrscheinlich, wonach der Ausbilder sucht.Antworten:
Weil der normale mathematische Begriff "Rest" nur für die Ganzzahldivision gilt. dh Division, die erforderlich ist, um einen ganzzahligen Quotienten zu erzeugen.
Um das Konzept des "Restes" auf reelle Zahlen zu erweitern, müssen Sie eine neue Art von "Hybrid" -Operation einführen, die einen ganzzahligen Quotienten für reelle Operanden erzeugen würde . Die Core C-Sprache unterstützt einen solchen Vorgang nicht, wird jedoch als Standardbibliotheksfunktion
fmod
sowie alsremainder
Funktion in C99 bereitgestellt . (Beachten Sie, dass diese Funktionen nicht identisch sind und einige Besonderheiten aufweisen. Insbesondere folgen sie nicht den Rundungsregeln der Ganzzahldivision.)quelle
(a/b)*b
bereits gleicha
[sofern eine solche Aussage für Gleitkommatypen gemacht werden kann],a%b
wäre also niemals besonders nützlich.%
Operators für Gleitkomma wäre vermutlicha-(a/b)*b
0 oder ein sehr kleiner Wert.Sie suchen nach fmod () .
Um Ihre Frage genauer zu beantworten, wurde der
%
Operator in älteren Sprachen nur als ganzzahlige modulare Unterteilung definiert, und in neueren Sprachen wurde beschlossen, die Definition des Operators zu erweitern.EDIT: Wenn ich eine Vermutung wetten würde, warum, würde ich sagen, dass die Idee der modularen Arithmetik aus der Zahlentheorie stammt und sich speziell mit ganzen Zahlen befasst.
quelle
Ich kann nicht wirklich für sagen sicher , aber ich würde vermuten , es meist historisch ist. Nicht wenige frühe C-Compiler unterstützten Gleitkomma überhaupt nicht. Es wurde später hinzugefügt, und selbst dann nicht als vollständig - meist der Datentyp wurde hinzugefügt, und die meisten primitiven Operationen in der Sprache unterstützt, aber alles andere auf der Standard - Bibliothek verlassen.
quelle
Der Modulo-Operator
%
in C und C ++ ist für zwei Ganzzahlen definiert.fmod()
Für die Verwendung mit Doubles steht jedoch eine Funktion zur Verfügung.quelle
sin(fmod(x,3.14))
oder ist sogarsin(fmod(x,M_PI))
nicht gleichsin(x)
für große Werte vonx
. Tatsächlich können sich die Werte um bis zu 2,0 unterscheiden.%
der Restoperator und kein Modulooperator?Die Einschränkungen sind in den Standards enthalten:
C11 (ISO / IEC 9899: 201x) §6.5.5 Multiplikative Operatoren
C ++ 11 (ISO / IEC 14882: 2011) §5.6 Multiplikative Operatoren
Die Lösung ist die Verwendung
fmod
, weshalb die Operanden von%
gemäß C99-Begründung §6.5.5 Multiplikative Operatoren in erster Linie auf den Integer-Typ beschränkt sind :quelle
Versuchen
fmod
quelle
Der Operator% gibt Ihnen einen REST (ein anderer Name für den Modul) einer Zahl. Für C / C ++ ist dies nur für ganzzahlige 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 unterteilt werden kann:
>>> 4 % math.pi 0.85840734641020688 >>> 4 - math.pi 0.85840734641020688 >>>
quelle
:P
Der
%
Operator funktioniert in C ++ nicht, wenn Sie versuchen, den Rest von zwei Zahlen zu finden, die beide vom TypFloat
oder sindDouble
.Daher können Sie versuchen, die
fmod
Funktion vonmath.h
/ zu verwenden,cmath.h
oder Sie können diese Codezeilen verwenden, um die Verwendung dieser Header-Datei zu vermeiden:float sin(float x) { float temp; temp = (x + M_PI) / ((2 *M_PI) - M_PI); return limited_sin((x + M_PI) - ((2 *M_PI) - M_PI) * temp ));
}}
quelle
"Der mathematische Begriff der Modulo-Arithmetik funktioniert auch für Gleitkommawerte, und dies ist eines der ersten Themen, die Donald Knuth in seinem Klassiker Die Kunst der Computerprogrammierung (Band I) behandelt. Das heißt, es war einst Grundwissen."
Der Gleitkommamoduloperator ist wie folgt definiert:
m = num - iquot*den ; where iquot = int( num/den )
Wie angegeben, scheint das No-Op des% -Operators für Gleitkommazahlen standardbezogen zu sein. Die CRTL bietet 'fmod' und normalerweise auch 'rest', um% für fp-Zahlen auszuführen. Der Unterschied zwischen diesen beiden liegt darin, wie sie mit der Zwischenrundung "iquot" umgehen.
'rest' verwendet runde bis nächste und 'fmod' verwendet einfaches Abschneiden.
Wenn Sie Ihre eigenen numerischen C ++ - Klassen schreiben, hindert Sie nichts daran, das No-Op-Erbe zu ändern, indem Sie einen überladenen Operator% einfügen.
Freundliche Grüße
quelle