std:: remquo, std:: remquof, std:: remquol
|
Definiert im Header
<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
/* floating-point-type */
remquo
(
/* floating-point-type */
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 im Header
<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)
Inhaltsverzeichnis |
Parameter
| x, y | - | Gleitkomma- oder Ganzzahlwerte |
| quo | - | Zeiger auf int zum Speichern des Vorzeichens und einiger Bits von x / y |
Rückgabewert
Bei Erfolg gibt den Gleitkomma-Rest der Division
x
/
y
zurück, wie in
std::remainder
definiert, und speichert in
*
quo
das Vorzeichen und mindestens drei der niederwertigsten Bits von
x
/
y
(formal: speichert einen Wert, dessen Vorzeichen dem Vorzeichen von
x
/
y
entspricht und dessen Betrag kongruent
modulo 2
n
zum Betrag des ganzzahligen Quotienten von
x
/
y
ist, wobei
n
eine implementierungsdefinierte Ganzzahl größer oder gleich
3
ist).
Wenn y null ist, ist der in * quo gespeicherte Wert nicht spezifiziert.
Wenn ein Domänenfehler auftritt, wird ein implementierungsdefinierter Wert zurückgegeben (NaN, sofern 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 Domänenfehler auftritt, wird null zurückgegeben.
Fehlerbehandlung
Fehler werden gemeldet, wie in math_errhandling spezifiziert.
Ein Domänenfehler kann auftreten, wenn y null ist.
Wenn die Implementierung IEEE-Gleitkommaarithmetik (IEC 60559) unterstützt,
- Der aktuelle Rundungsmodus hat keine Auswirkung.
- FE_INEXACT wird niemals ausgelöst.
- Wenn x ±∞ ist und y nicht NaN ist, wird NaN zurückgegeben und FE_INVALID ausgelöst.
- Wenn y ±0 ist und x nicht NaN ist, wird NaN zurückgegeben und FE_INVALID ausgelöst.
- Wenn entweder x oder y NaN ist, wird NaN zurückgegeben.
Hinweise
POSIX erfordert dass ein Domänenfehler auftritt, wenn x unendlich ist oder y null ist.
Diese Funktion ist nützlich bei der Implementierung periodischer Funktionen mit einer Periode, die exakt als Fließkommawert darstellbar ist: 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, aber wenn das Funktionsargument zuerst mit
std::remquo
reduziert wird, können die niederwertigen Bits des Quotienten verwendet werden, um das Vorzeichen und die Oktante des Ergebnisses innerhalb der Periode zu bestimmen, während der Rest zur Berechnung des Werts mit hoher Genauigkeit verwendet werden kann.
Auf einigen Plattformen wird dieser Vorgang durch Hardware unterstützt (und zum Beispiel auf Intel-CPUs lässt
FPREM1
bei Abschluss genau 3 Bits Präzision im Quotienten zurück).
Die zusätzlichen Überladungen müssen nicht exakt wie (A) bereitgestellt werden. Sie müssen lediglich sicherstellen, dass für ihr erstes Argument num1 und zweites Argument num2 :
|
(bis C++23) |
|
Falls
num1
und
num2
arithmetische Typen haben, dann hat
std
::
remquo
(
num1, num2, quo
)
denselben Effekt wie
std
::
remquo
(
static_cast
<
/*common-floating-point-type*/
>
(
num1
)
,
Falls kein solcher Gleitkommatyp mit dem höchsten Rang und Unterrang existiert, dann führt Überladungsauflösung nicht zu einem verwendbaren Kandidaten aus den bereitgestellten Überladungen. |
(seit C++23) |
Beispiel
#include <cfenv> #include <cmath> #include <iostream> #ifndef __GNUC__ #pragma STDC FENV_ACCESS ON #endif const double pi = std::acos(-1); // oder std::numbers::pi seit C++20 double cos_pi_x_naive(double x) { return std::cos(pi * x); } // Die Periode ist 2, Werte sind (0;0.5) positiv, (0.5;1.5) negativ, (1.5,2) positiv double cos_pi_x_smart(double x) { int quadrant; double rem = std::remquo(x, 1, &quadrant); quadrant = static_cast<unsigned>(quadrant) % 2; // Die Periode ist 2. return quadrant == 0 ? std::cos(pi * rem) : -std::cos(pi * rem); } int main() { std::cout << std::showpos << "naiv:\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' << "naiv:\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'; // Fehlerbehandlung 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 ausgelöst\n"; }
Mögliche Ausgabe:
naiv: 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 naiv: 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 ausgelöst
Siehe auch
|
(C++11)
|
berechnet Quotient und Rest der ganzzahligen Division
(Funktion) |
|
(C++11)
(C++11)
|
Rest der Gleitkomma-Divisionsoperation
(Funktion) |
|
(C++11)
(C++11)
(C++11)
|
vorzeichenbehafteter Rest der Divisionsoperation
(Funktion) |
|
C-Dokumentation
für
remquo
|
|