std::remquo, std::remquof, std::remquol

来自cppreference.com
< cpp‎ | numeric‎ | math
 
 
 
 
在标头 <cmath> 定义
(1)
float       remquo (float x, float y, int* quo );

double      remquo (double x, double y, int* quo );

longdouble remquo (longdouble x, longdouble y, int* quo );
(C++11 起)
(C++23 前)
constexpr/* floating-point-type */

            remquo (/* floating-point-type */ x,

                     /* floating-point-type */ y, int* quo );
(C++23 起)
float       remquof(float x, float y, int* quo );
(2) (C++11 起)
(C++23 起为 constexpr)
longdouble remquol(longdouble x, longdouble y, int* quo );
(3) (C++11 起)
(C++23 起为 constexpr)
在标头 <cmath> 定义
template<class Arithmetic1, class Arithmetic2 >

/* common-floating-point-type */

    remquo( Arithmetic1 x, Arithmetic2 y, int* quo );
(A) (C++11 起)
(C++23 起为 constexpr)
1-3) 以与 std::remainder() 相同的方式计算除法运算 x / y 的浮点数余数。此外还会将 x / y 的至少最低三位及符号存储到 quo,这足以确定结果在周期中的八分位。标准库提供所有以无 cv 限定的浮点数类型作为实参 xy 的类型的 std::remquo 重载。(C++23 起)
A) 为算术类型的所有其他组合提供额外重载。

目录

[编辑]参数

x, y - 浮点数或整数
quo - 用来存储 x / y 的符号和某些位的指向 int 的指针

[编辑]返回值

在成功时返回定义于 std::remainderx / y 的余数,并将 x / y 的符号和至少后三位有效数字存储到 *quo(正式而言,存储的值的符号是 x / y 的符号,而绝对值与 x / y 的整数商的绝对值对于 modulo 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
  • 如果 xy 是 NaN,那么返回 NaN。

[编辑]注解

POSIX 要求x 是无穷大或 y 为零时发生定义域错误。

此函数在实现周期可准确表示为浮点数值的周期函数时有用:对非常大的 x 计算 sin(πx) 时,直接调用 std::sin 可能导致巨大误差,但如果首先以 std::remquo 减小函数实参,那么商的低位可用来确定结果在周期中的八分位,同时余数可用来计算拥有高精度的值。

某些平台上硬件支持此运算(例如在 Intel CPU 上,FPREM1 在完成时于商中准确保留 3 位精度)。

额外重载不需要以 (A) 的形式提供。它们只需要能够对它们的第一个实参 num1 和第二个实参 num2 满足以下要求:

  • 如果 num1num2 具有 longdouble 类型,那么 std::remquo(num1, num2, quo)std::remquo(static_cast<longdouble>(num1),
                static_cast<longdouble>(num2), quo)
    的效果相同。
  • 否则,如果 num1 和/或 num2 具有 double 或整数类型,那么 std::remquo(num1, num2, quo)std::remquo(static_cast<double>(num1),
                static_cast<double>(num2), quo)
    的效果相同。
  • 否则,如果 num1num2 具有 float 类型,那么 std::remquo(num1, num2, quo)std::remquo(static_cast<float>(num1),
                static_cast<float>(num2), quo)
    的效果相同。
(C++23 前)

如果 num1num2 具有算术类型,那么 std::remquo(num1, num2, quo)std::remquo(static_cast</*公共浮点数类型*/>(num1),
            static_cast</*公共浮点数类型*/>(num2), quo)
的效果相同,其中 /*公共浮点数类型*/num1num2 的类型中浮点数转换等级浮点数转换子等级最高的浮点数类型,整数类型的实参被视为具有与 double 相等的浮点数转换等级。

如果不存在等级和子等级最高的浮点数类型,那么在重载决议时不会从提供的重载中产生可用的候选。

(C++23 起)

[编辑]示例

#include <cfenv>#include <cmath>#include <iostream>   #ifndef __GNUC__#pragma STDC FENV_ACCESS ON#endif   constdouble pi =std::acos(-1);// C++20 起也可以使用 std::numbers::pi   double cos_pi_x_naive(double x){returnstd::cos(pi * x);}   // 周期是 2,值在 (0,0.5) 和 (1.5,2) 中为正,在 (0.5;1.5) 中为负double cos_pi_x_smart(double x){int quadrant;double rem = std::remquo(x, 1, &quadrant); quadrant =static_cast<unsigned>(quadrant)%2;// 周期是 2return quadrant ==0?std::cos(pi * rem):-std::cos(pi * rem);}   int main(){std::cout<<std::showpos<<"朴素实现:\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'<<"优秀实现:\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'<<"朴素实现:\n"<<" cos(pi * 1000000000000.25) = "<< cos_pi_x_naive(1000000000000.25)<<'\n'<<" cos(pi * 1000000000001.25) = "<< cos_pi_x_naive(1000000000001.25)<<'\n'<<"优秀实现:\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";}

可能的输出:

朴素实现: cos(pi * 0.25) = +0.707107 cos(pi * 1.25) = -0.707107 cos(pi * 2.25) = +0.707107 优秀实现: cos(pi * 0.25) = +0.707107 cos(pi * 1.25) = -0.707107 cos(pi * 2.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

[编辑]参阅

计算整数除法的商和余数
(函数)[编辑]
(C++11)(C++11)
浮点数除法运算的余数
(函数)[编辑]
(C++11)(C++11)(C++11)
除法运算的有符号余数
(函数)[编辑]
remquo 的 C 文档
close