std::remquo, std::remquof, std::remquol
| Definiert in der Header-Datei <cmath> |
||
| (1) | ||
float remquo ( float x, float y, int* quo ); double remquo ( double x, double y, int* quo ); |
(seit C++11) (bis C++23) |
|
| constexpr /* gleitkommazahl-Typ */ remquo ( /* Gleitkommatyp */ x, |
(seit C++23) | |
| float remquof( float x, float y, int* quo ); |
(2) | (seit C++11) (constexpr seit C++23) |
| long double remquol( long double x, long double y, int* quo ); |
(3) | (seit C++11) (constexpr seit C++23) |
| Definiert in der Header-Datei <cmath> |
||
| template< class Arithmetic1, class Arithmetic2 > /* common-floating-point-type */ |
(A) | (seit C++11) (constexpr seit C++23) |
std::remquo für alle cv-unqualifizierten Gleitkommatypen als Typ der Parameter x und y bereit.(seit C++23)Inhalt |
[edit] Parameter
| x, y | - | Gleitkomma- oder Ganzzahlwerte |
| quo | - | Zeiger auf int, um das Vorzeichen und einige Bits von x / y zu speichern |
[edit] Rückgabewert
Bei Erfolg gibt der Gleitkomma-Rest der Division x / y zurück, wie in std::remainder definiert, und speichert in *quo das Vorzeichen und mindestens drei der niedrigsten Bits von x / y (formal wird ein Wert gespeichert, dessen Vorzeichen das Vorzeichen von x / y ist und dessen Betrag kongruent modulo 2n
zum Betrag des ganzzahligen Quotienten von x / y ist, wobei n eine implementierungsdefinierte ganze Zahl größer oder gleich 3 ist).
Wenn y Null ist, ist der Wert, der in *quo gespeichert wird, undefiniert.
Wenn ein Domänenfehler auftritt, wird ein implementierungsabhängiger Wert zurückgegeben (NaN, wo unterstützt).
Wenn ein Bereichsfehler aufgrund von Unterlauf auftritt, wird das korrekte Ergebnis zurückgegeben, wenn Subnormale unterstützt werden.
Wenn y Null ist, aber kein Bereichsfehler auftritt, wird Null zurückgegeben.
[edit] Fehlerbehandlung
Fehler werden wie in math_errhandling beschrieben gemeldet.
Ein Domänenfehler kann auftreten, wenn y null ist.
Wenn die Implementierung IEEE-Gleitkomma-Arithmetik (IEC 60559) unterstützt,
- Der aktuelle Rundungsmodus hat keinen Einfluss.
- FE_INEXACT wird nie ausgelöst.
- Wenn x ±∞ ist und y keine NaN ist, wird NaN zurückgegeben und FE_INVALID ausgelöst.
- Wenn y ±0 ist und x keine NaN ist, wird NaN zurückgegeben und FE_INVALID ausgelöst.
- Wenn entweder x oder y NaN ist, wird NaN zurückgegeben.
[edit] Anmerkungen
POSIX erfordert, dass ein Bereichsfehler auftritt, wenn x unendlich ist oder y Null ist.
Diese Funktion ist nützlich bei der Implementierung periodischer Funktionen mit exakt darstellbarer Periode als Gleitkommawert: Bei der Berechnung von sin(πx) für ein sehr großes x kann der direkte Aufruf von std::sin zu einem großen Fehler führen. Wenn jedoch das Funktionsargument zuerst mit std::remquo reduziert wird, können die niedrigwertigen Bits des Quotienten verwendet werden, um das Vorzeichen und den Oktanten des Ergebnisses innerhalb der Periode zu bestimmen, während der Rest zur hochpräzisen Berechnung des Wertes verwendet werden kann.
Auf einigen Plattformen wird diese Operation von der Hardware unterstützt (und beispielsweise auf Intel-CPUs hinterlässt FPREM1 bei Abschluss genau 3 Bits Präzision im Quotienten).
Die zusätzlichen Überladungen müssen nicht exakt wie (A) angegeben werden. Sie müssen nur ausreichen, um sicherzustellen, dass für ihr erstes Argument num1 und ihr zweites Argument num2
|
(bis C++23) |
|
Wenn num1 und num2 arithmetische Typen haben, hat std::remquo(num1, num2, quo) denselben Effekt wie std::remquo(static_cast</*gemeinsamer_gleitkommatyp*/>(num1), Wenn kein solcher Gleitkommazahltyp mit dem höchsten Rang und Subrang existiert, dann führt die Überladungsauflösung nicht zu einem nutzbaren Kandidaten aus den bereitgestellten Überladungen. |
(seit C++23) |
[edit] Beispiel
#include <cfenv> #include <cmath> #include <iostream> #ifndef __GNUC__ #pragma STDC FENV_ACCESS ON #endif const double pi = std::acos(-1); // or std::numbers::pi since C++20 double cos_pi_x_naive(double x) { return std::cos(pi * x); } // the period is 2, values are (0;0.5) positive, (0.5;1.5) negative, (1.5,2) positive double cos_pi_x_smart(double x) { int quadrant; double rem = std::remquo(x, 1, &quadrant); quadrant = static_cast<unsigned>(quadrant) % 2; // The period is 2. return quadrant == 0 ? std::cos(pi * rem) : -std::cos(pi * rem); } int main() { std::cout << std::showpos << "naive:\n" << " cos(pi * 0.25) = " << cos_pi_x_naive(0.25) << '\n' << " cos(pi * 1.25) = " << cos_pi_x_naive(1.25) << '\n' << " cos(pi * 2.25) = " << cos_pi_x_naive(2.25) << '\n' << "smart:\n" << " cos(pi * 0.25) = " << cos_pi_x_smart(0.25) << '\n' << " cos(pi * 1.25) = " << cos_pi_x_smart(1.25) << '\n' << " cos(pi * 2.25) = " << cos_pi_x_smart(2.25) << '\n' << "naive:\n" << " cos(pi * 1000000000000.25) = " << cos_pi_x_naive(1000000000000.25) << '\n' << " cos(pi * 1000000000001.25) = " << cos_pi_x_naive(1000000000001.25) << '\n' << "smart:\n" << " cos(pi * 1000000000000.25) = " << cos_pi_x_smart(1000000000000.25) << '\n' << " cos(pi * 1000000000001.25) = " << cos_pi_x_smart(1000000000001.25) << '\n'; // error handling std::feclearexcept(FE_ALL_EXCEPT); int quo; std::cout << "remquo(+Inf, 1) = " << std::remquo(INFINITY, 1, &quo) << '\n'; if (fetestexcept(FE_INVALID)) std::cout << " FE_INVALID raised\n"; }
Mögliche Ausgabe
naive: cos(pi * 0.25) = +0.707107 cos(pi * 1.25) = -0.707107 cos(pi * 2.25) = +0.707107 smart: cos(pi * 0.25) = +0.707107 cos(pi * 1.25) = -0.707107 cos(pi * 2.25) = +0.707107 naive: cos(pi * 1000000000000.25) = +0.707123 cos(pi * 1000000000001.25) = -0.707117 smart: cos(pi * 1000000000000.25) = +0.707107 cos(pi * 1000000000001.25) = -0.707107 remquo(+Inf, 1) = -nan FE_INVALID raised
[edit] Siehe auch
| (C++11) |
berechnet Quotient und Rest der ganzzahligen Division (Funktion) |
| (C++11)(C++11) |
Rest der Gleitkommadivisionsoperation (Funktion) |
| (C++11)(C++11)(C++11) |
Vorzeichenbehafteter Rest der Divisionsoperation (Funktion) |
| C-Dokumentation für remquo
| |