remquo, remquof, remquol
Определено в заголовочном файле <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) |
x/y так же, как это делает функция remainder(). Кроме того, знак и как минимум три последних бита x/y сохраняются в quo, чего достаточно, чтобы определить октант результата в пределах периода.long double, вызывается remquol. В противном случае, если какой-либо аргумент, не являющийся указателем, имеет целочисленный тип или тип double, вызывается remquo. В противном случае вызывается 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, возвращается NaN и вызываетсяFE_INVALID - Если
yравен ±0, аxне является NaN, возвращается NaN и вызываетсяFE_INVALID - Если
xилиyявляется NaN, возвращается NaN
Примечания
POSIX требует, чтобы ошибка области определения возникала, если x бесконечно или y равен нулю.
Эта функция полезна при реализации периодических функций с периодом, точно представимым в виде числа с плавающей точкой: при вычислении sin(πx) для очень большого x непосредственный вызов sin может привести к большой погрешности, но если сначала уменьшить аргумент функции с помощью remquo, младшие биты частного можно использовать для определения знака и октанта результата в пределах периода, а остаток — для вычисления значения с высокой точностью.
На некоторых платформах эта операция поддерживается аппаратно (и, например, на процессорах Intel 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)
{
const 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)
{
const double pi = acos(-1);
int extremum;
double rem = remquo(x, 1, &extremum);
extremum = (unsigned)extremum % 2; // keep 1 bit to determine nearest extremum
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));
// 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
Ссылки
- Стандарт C23 (ISO/IEC 9899:2024):
- 7.12.10.3 Функции remquo (стр.: TBD)
- 7.25 Типо-обобщённая математика <tgmath.h> (стр.: TBD)
- F.10.7.3 Функции remquo (стр.: TBD)
- Стандарт C17 (ISO/IEC 9899:2018):
- 7.12.10.3 Функции remquo (стр.: 186)
- 7.25 Типо-обобщённая математика <tgmath.h> (стр.: 272-273)
- F.10.7.3 Функции remquo (стр.: 385)
- Стандарт C11 (ISO/IEC 9899:2011):
- 7.12.10.3 Функции remquo (стр.: 255)
- 7.25 Типо-обобщённая математика <tgmath.h> (стр.: 373-375)
- F.10.7.3 Функции remquo (стр.: 529)
- Стандарт C99 (ISO/IEC 9899:1999):
- 7.12.10.3 Функции remquo (стр.: 236)
- 7.22 Типо-обобщённая математика <tgmath.h> (стр.: 335-337)
- F.9.7.3 Функции remquo (стр.: 465)
См. также
|
(C99) | вычисляет частное и остаток от целочисленного деления (функция) |
|
(C99)(C99) | вычисляет остаток от деления чисел с плавающей точкой (функция) |
|
(C99)(C99)(C99) | вычисляет знаковый остаток от деления чисел с плавающей точкой (функция) |
Документация C++ для remquo |
|
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/c/numeric/math/remquo