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 起) (constexpr 自 C++23 起) |
long double remquol( long double x, long double y, int* quo ); |
(3) | (自 C++11 起) (constexpr 自 C++23 起) |
定义于头文件 <cmath> |
||
template< class Arithmetic1, class Arithmetic2 > /* 共同浮点类型 */ |
(A) | (自 C++11 起) (constexpr 自 C++23 起) |
std::remquo
的重载,作为参数 x 和 y 的类型。(自 C++23 起)内容 |
[编辑] 参数
x, y | - | 浮点值或整数值 |
quo | - | 指向 int 的指针,用于存储 x / y 的符号和一些位 |
[编辑] 返回值
如果成功,则返回除法 x / y 的浮点余数,如 std::remainder 中所定义,并在 *quo 中存储 x / y 的符号和至少三个最低有效位(正式地,存储一个值,该值的符号是 x / y 的符号,并且其大小与 x / y 的整数商的大小模 2n
同余,其中 n 是大于或等于 3 的实现定义的整数)。
如果 y 为零,则存储在 *quo 中的值是未指定的。
如果发生域错误,则返回实现定义的值(如果支持,则为 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</*共同浮点类型*/>(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
|