非常教程

C参考手册

数值 | Numerics

remquof

在头文件<math.h>中定义

float remquof( float x, float y, int *quo );

(1)

(since C99)

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

(2)

(since C99)

long double remquol( long double x, long double y, int *quo );

(3)

(since C99)

Defined in header <tgmath.h>

#define remquo( x, y, quo )

(4)

(since C99)

1-3)x/y根据remainder()函数计算除法运算的浮点余数。此外,符号和至少三个最后的比特x/y将被存储在其中quo,足以确定一段时间内结果的八分之一。

4)类型 - 通用宏:如果任何非指针参数具有类型long doubleremquol则被调用。否则,如果任何非指针参数具有整数类型或具有类型doubleremquo则被调用。否则,remquof被调用。

参数

x,y

-

浮点值

quo

-

指向一个整数值的指针来存储符号和x / y的一些位

返回值

如果成功,则返回除法的浮点余x/y中定义remainder,并存储,在*quo,符号和至少三个的至少显著位x/y(正式地说,存储其符号是符号的值x/y,其大小是全等模2n

x/y其中n是大于或等于3的实现定义的整数的整数商数的大小)。

如果y为零,则存储的值*quo未指定。

如果发生域错误,则返回实现定义的值(NaN,如果支持)。

如果由于下溢而发生范围错误,如果支持子正常则返回正确的结果。

如果y为零,但域错误不会发生,则返回零。

错误处理

按照math_errhandling中的指定报告错误。

如果y为零,则可能会出现域错误。

如果实现支持IEEE浮点运算(IEC 60559),

  • 当前的舍入模式不起作用。
  • FE_INEXACT 从未被提出
  • 如果x是±∞并且y不是NaN,则返回并FE_INVALID提升NaN
  • 如果y是±0并且x不是NaN,则返回并FE_INVALID提升NaN
  • 如果是x或者y是NaN,则返回NaN

笔记

如果x是无限的或者y是零,POSIX要求发生域错误。

这个函数在实现周期函数时非常有用,该周期函数的周期可以精确地表示为一个浮点值:当计算一个非常大的sin(πx)时xsin直接调用可能会导致大的错误,但是如果函数参数首先被减少remquo,可以使用商的低位比特来确定该周期内结果的符号和八分之一,而余数可以用于以高精度计算该值。

在某些平台上,该操作由硬件支持(例如,在Intel CPU上,FPREM1精确度仅为3位)。

#include <stdio.h>
#include <math.h>
#include <fenv.h>
 
#pragma STDC FENV_ACCESS ON
double cos_pi_x_naive(double x)
{
    double pi = acos(-1);
    return 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 = remquo(x, 1, &quadrant);
    quadrant = (unsigned)quadrant % 4; // keep 2 bits to determine quadrant
 
    double pi = acos(-1);
    switch(quadrant) {
        case 0: return cos(pi * rem);
        case 1: return -cos(pi * rem);
        case 2: return -cos(pi * rem);
        case 3: return 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));
    // error handling
    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

参考

  • C11标准(ISO / IEC 9899:2011):
    • 7.12.10.3遥控功能(p:255)
    • 7.25类型通用数学<tgmath.h>(p:373-375)
    • F.10.7.3遥控功能(p:529)
  • C99标准(ISO / IEC 9899:1999):
    • 7.12.10.3遥控功能(p:236)
    • 7.22类型通用数学<tgmath.h>(p:335-337)
    • F.9.7.3遥控功能(p:465)
C

C 语言是一门通用计算机编程语言,应用广泛。C 语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。