Преобразование / Квантование диапазона с плавающей запятой в диапазон целых чисел

StackOverflow https://stackoverflow.com/questions/599976

Вопрос

Допустим, у меня есть значение с плавающей точкой в диапазоне [0, 1], и я хочу квантовать и сохранить его в байте без знака.Звучит как простая задача, но на самом деле это довольно сложно:

Очевидное решение выглядит следующим образом:

unsigned char QuantizeFloat(float a)
{
  return (unsigned char)(a * 255.0f);
}

Это работает до тех пор, пока я получаю все числа от 0 до 255, но распределение целых чисел неравномерно.Функция возвращает только 255 если a - это точно 1.0f.Не очень хорошее решение.

Если я делаю правильное округление, я просто сдвигаю проблему:

unsigned char QuantizeFloat(float a)
{
  return (unsigned char)(a * 255.0f + 0.5f);
}

Вот результат 0 охватывает только половину диапазона значений с плавающей запятой, чем любое другое число.

Как мне выполнить квантование с равным распределением диапазона с плавающей запятой?В идеале я хотел бы получить равное распределение целых чисел, если я буду квантовать равномерно распределенные случайные числа с плавающей запятой.

Есть какие-нибудь идеи?


Кстати:Кроме того, мой код написан на C, проблема не зависит от языка.Для людей, не относящихся к категории С:Просто предположим , что float Для int преобразование усекает значение с плавающей точкой.

Редактировать: Поскольку у нас здесь возникла некоторая путаница:Мне нужно сопоставление, которое сопоставляет наименьшее входное значение с плавающей точкой (0) с наименьшим символом без знака, а наибольшее значение с плавающей точкой в моем диапазоне (1.0f) с наибольшим байтом без знака (255).

Это было полезно?

Решение

Как насчет a * 256f с проверкой на уменьшение 256 до 255?Так что что-то вроде:

return (unsigned char) (min(255, (int) (a * 256f)));

(Для подходящей функции min на вашей платформе - я не могу вспомнить функцию C для нее.)

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

Другие советы

Я думаю, что то, что вы ищете, это:

unsigned char QuantizeFloat (float a)
{
  return (unsigned char) (a * 256.0f);
}

Это сопоставит однородные значения с плавающей точкой в [0, 1] с однородными байтовыми значениями в [0, 255].Все значения в [i/256, (i+1)/256[ (то есть исключая (i+1)/256), для i в 0..255 сопоставляются с i.Что может быть нежелательным, так это то, что 1.0f сопоставляется с 256.0f, который оборачивается вокруг 0.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top