remquo, remquof, remquol
|
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
ヘッダーで定義
<math.h>
|
||
|
float
remquof
(
float
x,
float
y,
int
*
quo
)
;
|
(1) | (C99以降) |
|
double
remquo
(
double
x,
double
y,
int
*
quo
)
;
|
(2) | (C99以降) |
|
long
double
remquol
(
long
double
x,
long
double
y,
int
*
quo
)
;
|
(3) | (C99以降) |
|
ヘッダーで定義
<tgmath.h>
|
||
|
#define remquo( x, y, quo )
|
(4) | (C99以降) |
remquol
が呼び出される。それ以外の場合、非ポインタ引数が整数型または
double
型の場合、
remquo
が呼び出される。それ以外の場合、
remquof
が呼び出される。
目次 |
パラメータ
| x, y | - | 浮動小数点値 |
| quo | - | 符号と x / y の一部ビットを格納する整数値へのポインタ |
戻り値
成功した場合、 remainder で定義される除算 x / y の浮動小数点剰余を返し、 * quo に x / y の符号と少なくとも下位3ビットを格納する(形式的には、符号が x / y の符号と一致し、大きさが x / y の整数商の大きさと 2 n を法として合同な値を格納する。ここで 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)
を計算する場合、
sin
を直接呼び出すと大きな誤差が生じる可能性がありますが、関数引数を最初に
remquo
で還元すると、商の下位ビットを使用して周期内の結果の符号とオクタントを決定でき、剰余を使用して高精度で値を計算できます。
一部のプラットフォームでは、この演算はハードウェアでサポートされています(例えば、Intel CPUでは、
FPREM1
が商に正確に3ビットの精度を残します)。
例
#include <fenv.h> #include <math.h> #include <stdio.h> #ifndef __GNUC__ #pragma STDC FENV_ACCESS ON #endif double cos_pi_x_naive(double x) { const double pi = acos(-1); return cos(pi * x); } // 周期は2、値は(0;0.5)で正、(0.5;1.5)で負、(1.5,2)で正 double cos_pi_x_smart(double x) { const double pi = acos(-1); int extremum; double rem = remquo(x, 1, &extremum); extremum = (unsigned)extremum % 2; // 最寄りの極値を決定するために1ビットを保持 return extremum ? -cos(pi * rem) : cos(pi * rem); } int main(void) { printf("cos(pi * 0.25) = %f\n", cos_pi_x_naive(0.25)); printf("cos(pi * 1.25) = %f\n", cos_pi_x_naive(1.25)); printf("cos(pi * 1000000000000.25) = %f\n", cos_pi_x_naive(1000000000000.25)); printf("cos(pi * 1000000000001.25) = %f\n", cos_pi_x_naive(1000000000001.25)); printf("cos(pi * 1000000000000.25) = %f\n", cos_pi_x_smart(1000000000000.25)); printf("cos(pi * 1000000000001.25) = %f\n", cos_pi_x_smart(1000000000001.25)); // エラー処理 feclearexcept(FE_ALL_EXCEPT); int quo; printf("remquo(+Inf, 1) = %.1f\n", remquo(INFINITY, 1, &quo)); if (fetestexcept(FE_INVALID)) puts(" FE_INVALID raised"); }
出力例:
cos(pi * 0.25) = 0.707107
cos(pi * 1.25) = -0.707107
cos(pi * 1000000000000.25) = 0.707123
cos(pi * 1000000000001.25) = -0.707117
cos(pi * 1000000000000.25) = 0.707107
cos(pi * 1000000000001.25) = -0.707107
remquo(+Inf, 1) = -nan
FE_INVALID raised
参考文献
- C23規格 (ISO/IEC 9899:2024):
-
- 7.12.10.3 remquo関数群 (p: TBD)
-
- 7.25 総称数学 <tgmath.h> (p: TBD)
-
- F.10.7.3 remquo関数群 (p: TBD)
- C17規格 (ISO/IEC 9899:2018):
-
- 7.12.10.3 remquo関数群 (p: 186)
-
- 7.25 総称数学 <tgmath.h> (p: 272-273)
-
- F.10.7.3 remquo関数群 (p: 385)
- C11規格 (ISO/IEC 9899:2011):
-
- 7.12.10.3 remquo関数 (p: 255)
-
- 7.25 総称数学 <tgmath.h> (p: 373-375)
-
- F.10.7.3 remquo関数 (p: 529)
- C99規格 (ISO/IEC 9899:1999):
-
- 7.12.10.3 remquo関数 (p: 236)
-
- 7.22 総称数学 <tgmath.h> (p: 335-337)
-
- F.9.7.3 remquo関数 (p: 465)
関連項目
|
(C99)
|
整数除算の商と余りを計算する
(関数) |
|
(C99)
(C99)
|
浮動小数点除算演算の余りを計算する
(関数) |
|
(C99)
(C99)
(C99)
|
浮動小数点除算演算の符号付き余りを計算する
(関数) |
|
C++ documentation
for
remquo
|
|