Поиск следующего представимого номера IEEE 754 (по направлению к -INF) с помощью C?

Я пытаюсь написать функцию, которая принимает 32-битное число с плавающей запятой (которое было преобразовано из 32-битной двоичной строки) и возвращает предыдущее представляемое число с плавающей запятой в 32-битном двоичном формате. Пока у меня есть преобразование из двоичного в плавающее, но у меня возникают проблемы с пониманием того, как найти следующее представляемое значение IEEE 754. Разве вы не можете просто вычесть наименьшее возможное представимое значение (000 0000 0000 0000 0000 0001)? Кроме того, каковы (если есть) преимущества преобразования из IEEE 754 в число с плавающей запятой перед поиском ближайшего представимого двоичного значения?

Пока у меня есть только функция, которая преобразует число с плавающей запятой в 32-битный двоичный файл простой точности. Я бы включил свой код, но это для школы, поэтому я не уверен, размещая его в Интернете / получая явные исправления и советы.


person user3614396    schedule 19.10.2014    source источник
comment
1) Выложи то, что есть. 2) Подсказка: float --> двоичный, двоичный ++ или --, двоичный --> float.   -  person chux - Reinstate Monica    schedule 19.10.2014
comment
Что это за преобразование из 32-битной двоичной строки в 32-битную float?   -  person Keith Thompson    schedule 19.10.2014
comment
Моя программа принимает двоичный файл в виде массива целых чисел[32], а затем переводит знак, показатель степени и мантиссу в число с плавающей запятой.   -  person user3614396    schedule 20.10.2014


Ответы (1)


В: Нельзя ли просто вычесть наименьшее возможное представимое значение?
О: Нет. Числа с плавающей запятой распределяются логарифмически, а не линейно. Вычитание любого фиксированного значения, такого как 0,000001, не повлияет на большие float и окажет слишком большое влияние на крошечные float значения.

Q: Каковы преимущества преобразования из IEEE 754 в Float перед поиском ближайшего представляемого двоичного значения?
A: "IEEE 754" в "Float" обычно имеют один и тот же тип - преобразование не происходит. Оба являются 32-битными числовыми представлениями.

Следование зависит от того, является ли float IEEE 754 binary32. Это также зависит от соответствия порядков байтов int32_t и float. Он возвращает NaN, когда вводится -INF.

float nextdown(float x) {
  union {
    float x;
    int32_t i;
  } u;
  u.x = x;
  if (u.i > 0) {
    u.i--;
  }
  else if (u.i < 0) {
    u.i++;
  }
  else {
    u.i = 0x80000001;
  }
  return u.x;
}

Вышеприведенное не очень хорошо обрабатывает NaN. Простой дополнительный тест:

float nextdown(float x) {
  // catch NaN
  if (x != x) return x;

  union {
    float x;
    int32_t i;
  } u;
  ...

Примечание. Желаемая функция OP почти такая же, как <math.h> nextafterf(x,-1.0f/0.0f), которая использовалась для тестирования этого кода. Различия в NaN и -INF.

person chux - Reinstate Monica    schedule 19.10.2014
comment
Я просмотрел функцию nextafterf() из math.h, но не смог понять ее достаточно, чтобы эффективно применить ее аспекты к моему коду. - person user3614396; 19.10.2014
comment
@ user3614396 nextafterf() принимает 2 аргумента x и y. Он возвращает следующий представляемый float ближайший x в направлении y. Итак, nextafterf(1.0f, 2.0f) возвращает число чуть больше 1.0f. nextafterf(1.0f, 0.0f) возвращает число чуть меньше 1.0f. nextafterf(1.0f, 1.0f) возвращает 1.0f. - person chux - Reinstate Monica; 19.10.2014