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 /* 浮點型別 */ remquo ( /* 浮點型別 */ 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
的過載,作為引數 x 和 y 的型別。(C++23 起)目錄 |
[編輯] 引數
x, y | - | 浮點數或整數值 |
quo | - | 指向 int 的指標,用於儲存 x / y 的符號和一些位 |
[編輯] 返回值
如果成功,返回除法 x / y 的浮點餘數,其定義與 std::remainder 相同,並在 *quo 中儲存 x / y 的符號和至少三個最低有效位(形式上,儲存一個值,其符號為 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); // 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"; }
可能的輸出
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 文件 關於 remquo
|