remquo, remquof, remquol

来自cppreference.com
< c‎ | numeric‎ | math
 
 
 
常用数学函数
类型
(C99)(C99)    

(C99)(C99)    

函数
基本运算
remquo
(C99)
(C99)
(C99)
(C99)(C99)(C99)(C23)
最大/最小运算
(C99)
(C23)    
指数函数
(C23)
(C99)
(C99)
(C23)
(C23)
(C99)
(C99)(C23)
(C23)
(C23)
幂函数
(C99)
(C23)
(C23)
(C99)
(C23)
(C23)
三角及双曲函数
(C23)
(C23)
(C23)
(C23)
(C99)
(C99)
(C99)
误差及伽马函数
(C99)
(C99)
(C99)
(C99)
临近整数的浮点运算
(C99)(C99)(C99)
(C99)
(C99)(C99)(C99)
(C23)(C23)(C23)(C23)
浮点操作函数
(C99)(C99)
(C99)(C23)
(C99)
窄化运算
(C23)
(C23)
(C23)
(C23)
(C23)
(C23)
量与量指数函数
十进制重编码函数
全序与载荷函数
分类
(C99)
(C99)
(C99)
(C23)
宏常量
特殊浮点值
(C99)(C23)
参数与返回值
(C99)(C99)(C99)(C99)(C99)    
错误处理
(C99)    

 
在标头 <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 起)
1-3) 计算除法运算 x/y 的浮点余数,如 remainder() 函数所为。另外,将存储 x/y 的至少最低三位及符号于 quo,这足以确定结果在周期中的八分位。
4) 泛型宏:若任何非指针实参拥有 long double 类型,则调用 remquol。否则,若任何非指针实参拥有整数类型或 double 类型,则调用 remquo。否则,调用 remquof

参数

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

返回值

若成功,则返回定义于 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) 时,直接调用 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)
{
    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 The remquo functions (第 TBD 页)
  • 7.25 Type-generic math <tgmath.h> (第 TBD 页)
  • F.10.7.3 The remquo functions (第 TBD 页)
  • C17 标准(ISO/IEC 9899:2018):
  • 7.12.10.3 The remquo functions (第 186 页)
  • 7.25 Type-generic math <tgmath.h> (第 272-273 页)
  • F.10.7.3 The remquo functions (第 385 页)
  • C11 标准(ISO/IEC 9899:2011):
  • 7.12.10.3 The remquo functions (第 255 页)
  • 7.25 Type-generic math <tgmath.h> (第 373-375 页)
  • F.10.7.3 The remquo functions (第 529 页)
  • C99 标准(ISO/IEC 9899:1999):
  • 7.12.10.3 The remquo functions (第 236 页)
  • 7.22 Type-generic math <tgmath.h> (第 335-337 页)
  • F.9.7.3 The remquo functions (第 465 页)

参阅

计算整数除法的商和余数
(函数)
(C99)(C99)
计算浮点除法运算的余数
(函数)
计算浮点除法运算的带符号余数
(函数)