Выразите наибольшее количество с плавающей запятой меньше 1 - PullRequest
13 голосов
/ 29 декабря 2010

Я делал некоторые вычисления округления и натолкнулся на вопрос. Как я могу выразить наибольшее количество меньше 1 для данного типа с плавающей запятой?

То есть, как я пишу / представляю значение x такое, что x < 1, x + y >= 1 для любого y > 0.

В дробях это будет x = (q-1)/q, где q - это точность типа. Например, если вы рассчитываете с шагом 1/999, тогда x = 998/999.

Для данного типа (float, double, long double), как можно выразить значение x в коде?


Мне также интересно, существует ли такое значение для всех значений y. То есть, когда показатель y's становится меньше, возможно, отношение больше не выполняется. Так что ответ с некоторым ограничением диапазона на y также приемлем. (Значение x, которое я хочу, все еще существует, отношения могут просто неправильно выражать его.)

Ответы [ 6 ]

12 голосов
/ 29 декабря 2010

C99 определяет nextafter() функцию. Используйте это как

#include <math.h>
double under_one = nextafter(1, 0);
4 голосов
/ 29 декабря 2010

Все остальные правы, что большее значение, меньшее 1, равно 1-FLT_EPSILON, в плавающей точке оно не может соответствовать условию x < 1, x + y >= 1 для любого y > 0, если только вы не используете округление в большую сторону.

Причина в том, что расстояние между 1 и предыдущим (которое составляет FLT_EPSILON ~ 1.2E-7) намного больше, чем минимально представимое положительное число FLT_MIN, которое составляет ~ 1.2E-38.Таким образом, существует класс чисел (FLT_MIN ... FLT_EPSILON/2 при округлении до ближайшего значения, что по умолчанию для большинства систем), для которого (1-FLT_EPSILON)+y == (1-FLT_EPSILON) < 1.

2 голосов
/ 29 декабря 2010

Есть способ получить наименьшее количество, которое при добавлении к 1 даст наименьшее выраженное количество больше 1. Это std::numeric_limits<type>::epsilon(). Если вы докажете, что это количество равно тому, которое вы ищете, это то, что вы хотите:

шаблон статического _Tp std :: numeric_limits <_Tp> :: epsilon () throw () [inline, static] Эпсилон машины: разница между 1 и наименьшим значением больше 1, которое может быть представлено.

1 голос
/ 20 ноября 2015

Функция nextafter() хорошо работает @ qrdl

#include <math.h>
// find next double from 1.0 working towards 0.0
double before_1 = nextafter(1.0, 0.0);

Еще сделать это во время компиляции, как прокомментировано @ OP inочень переносимая мода:

#include <float.h>
double before_1 = 1.0 - DBL_EPSILON/FLT_RADIX;

DBL_EPSILON - абсолютная разница между 1,0 и следующим больше double.

FLT_RADIX - основание (база) системы с плавающей точкой.Часто 2. Используются такие значения, как 16 и 10.

1 голос
/ 29 декабря 2010

Согласно стандарту IEEE 754, версия с одинарной точностью (32-разрядная) 1.0 имеет представление 0x3F800000. Мы можем записать это в двоичном виде как 0 01111111 (1) 00000000000000000000000, что означает:

sign = 0
biased exponent = 01111111 = 0x7F, so exponent = -23 (decimal)
mantissa = 0x800000 (the (1) in parentheses is the implied msb)

Таким образом, значение равно 0x800000 * 2 ^ -23, что равно 1,0. Следующее наименьшее число с одинарной точностью -

0 01111110 (1)11111111111111111111111

или 0x3F7FFFFF или 0xFFFFFF * 2 ^ -24, что составляет около 0,999999994.

1 голос
/ 29 декабря 2010

Представление IEEE 754 имеет свойство, состоящее в том, что для чисел, которые являются положительными, а не NaN порядок совпадает с порядком в битовых комбинациях, рассматриваемых как целые числа.битовая комбинация числа с плавающей запятой 1.0 как целое число, уменьшает это число, а затем заново интерпретирует его как число с плавающей запятой, чтобы получить число с плавающей запятой чуть ниже единицы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...