std:: remquo, std:: remquof, std:: remquol
|
ヘッダーで定義
<cmath>
|
||
| (1) | ||
|
float
remquo
(
float
x,
float
y,
int
*
quo
)
;
double
remquo
(
double
x,
double
y,
int
*
quo
)
;
|
(C++11以降)
(C++23以前) |
|
|
constexpr
/* floating-point-type */
remquo
(
/* floating-point-type */
x,
|
(C++23以降) | |
|
float
remquof
(
float
x,
float
y,
int
*
quo
)
;
|
(2) |
(C++11以降)
(C++23以降constexpr) |
|
long
double
remquol
(
long
double
x,
long
double
y,
int
*
quo
)
;
|
(3) |
(C++11以降)
(C++23以降constexpr) |
|
ヘッダーで定義
<cmath>
|
||
|
template
<
class
Arithmetic1,
class
Arithmetic2
>
/* common-floating-point-type */
|
(A) |
(C++11以降)
(C++23以降constexpr) |
std::remquo
のオーバーロードを提供する。
(C++23以降)
目次 |
パラメータ
| x, y | - | 浮動小数点または整数値 |
| quo | - | int へのポインタで、 x / y の符号と一部のビットを格納する |
戻り値
成功した場合、x/yの除算の浮動小数点剰余を
std::remainder
で定義されている通りに返し、
*quo
に
x/y
の符号と少なくとも下位3ビットの情報を格納する
(形式的には、
x/y
の符号と同じ符号を持ち、その大きさが
2n
を法として
x/y
の整数商の大きさと合同な値を格納する。ここで
n
は3以上の実装定義の整数である)。
y がゼロの場合、 * quo に格納される値は未定義です。
定義域エラーが発生した場合、実装定義の値が返されます(NaNがサポートされている場合はNaN)。
アンダーフローによる範囲エラーが発生した場合、サブノーマルがサポートされている場合は正しい結果が返されます。
y がゼロであるが、定義域エラーが発生しない場合、ゼロが返されます。
エラーハンドリング
エラーは math_errhandling で指定された通りに報告されます。
y がゼロの場合、定義域エラーが発生する可能性があります。
IEEE浮動小数点演算(IEC 60559)を実装がサポートしている場合、
- 現在の 丸めモード は効果を持ちません。
- FE_INEXACT は決して発生しません。
- x が±∞で、 y がNaNでない場合、NaNが返され、 FE_INVALID が発生します。
- y が±0で、 x がNaNでない場合、NaNが返され、 FE_INVALID が発生します。
- x または y のいずれかがNaNの場合、NaNが返されます。
注記
POSIXでは 、 x が無限大または y がゼロの場合、定義域エラーが発生することが要求されています。
この関数は、周期が浮動小数点値として正確に表現可能な周期関数を実装する際に有用です:非常に大きな
x
に対して
sin(πx)
を計算する場合、
std::sin
を直接呼び出すと大きな誤差が生じる可能性がありますが、関数引数を最初に
std::remquo
で還元すると、商の下位ビットを使用して周期内の結果の符号とオクタントを決定できる一方、剰余を使用して高精度で値を計算できます。
一部のプラットフォームでは、この演算はハードウェアでサポートされています(例えば、Intel CPUでは、
FPREM1
は完了時に商の精度を正確に3ビット残します)。
追加のオーバーロードは (A) と完全に同一である必要はありません。それらは、第一引数 num1 と第二引数 num2 について以下を保証するのに十分であればよいのです:
|
(C++23以前) |
|
num1
と
num2
が算術型を持つ場合、
std
::
remquo
(
num1, num2, quo
)
は
std
::
remquo
(
static_cast
<
/*common-floating-point-type*/
>
(
num1
)
,
そのような最大のランクとサブランクを持つ浮動小数点型が存在しない場合、 オーバーロード解決 は提供されたオーバーロードから使用可能な候補を結果として生成しない。 |
(C++23以降) |
例
#include <cfenv> #include <cmath> #include <iostream> #ifndef __GNUC__ #pragma STDC FENV_ACCESS ON #endif const double pi = std::acos(-1); // または C++20 以降では std::numbers::pi double cos_pi_x_naive(double x) { return std::cos(pi * x); } // 周期は2、(0;0.5)で正、(0.5;1.5)で負、(1.5,2)で正の値を取る double cos_pi_x_smart(double x) { int quadrant; double rem = std::remquo(x, 1, &quadrant); quadrant = static_cast<unsigned>(quadrant) % 2; // 周期は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'; // エラー処理 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 が発生\n"; }
出力例:
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
関連項目
|
(C++11)
|
整数除算の商と余りを計算する
(関数) |
|
(C++11)
(C++11)
|
浮動小数点除算操作の余り
(関数) |
|
(C++11)
(C++11)
(C++11)
|
除算操作の符号付き余り
(関数) |
|
C documentation
for
remquo
|
|