Преобразовать / квантовать диапазон с плавающей точкой в ​​целочисленный диапазон - PullRequest
8 голосов
/ 01 марта 2009

Скажем, у меня есть число с плавающей точкой в ​​диапазоне [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, проблема не зависит от языка. Для людей не из C: просто предположим, что преобразование float в int усекает число с плавающей запятой.

РЕДАКТИРОВАТЬ: Так как у нас была некоторая путаница здесь: мне нужно отображение, которое отображает наименьшее входное значение с плавающей запятой (0) на наименьший беззнаковый символ, и наибольшее значение с плавающей точкой в ​​моем диапазоне (1,0f) старший байт без знака (255).

Ответы [ 2 ]

11 голосов
/ 01 марта 2009

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

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

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

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

1 голос
/ 01 марта 2009

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

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.

...