Альтернатива с плавающей точкой для хранения простых дробных значений

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

0.0 <= x < 1.0

Мотивация для этого состоит в том, чтобы попытаться уменьшить количество байтов, используемых для хранения этих данных (приложение сильно связано с памятью и пропускной способностью ввода / вывода). В настоящее время используется 32-битное представление с плавающей точкой, 16-битное с плавающей точкой оказывается недостаточно точным.

Мои первые мысли — попытаться сохранить данные в 16-разрядном целом числе и просто использовать схему:

x/(2^16 - 1) [x is an unsigned short]

Чтобы алгоритмы оставались в основном одинаковыми и чтобы использовались те же аппаратные операции с плавающей запятой (по крайней мере, на первых порах), в идеале я хотел бы продолжать преобразовывать это дробное представление в представление с плавающей запятой, выполняя операцию (операции), затем преобразование обратно в дробное представление для хранения.

Очевидно, что между этими двумя совершенно разными неточными представлениями будет потеря точности, но для нашего приложения, я подозреваю, это может быть приемлемым компромиссом.

Я провел некоторое исследование, глядя на то, что в настоящее время существует, что может дать нам хорошую отправную точку. Статья «Что должен знать каждый компьютерщик об арифметике с плавающей точкой» (http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) заставил меня взглянуть на несколько других, «За пределами плавающей точки» (home.ccil.org/~cowan/temp/p319-clenshaw.pdfбыть одним из таких примеров.

Может кто-нибудь указать мне на другие примеры представлений, которые люди использовали в другом месте, которые могли бы удовлетворить эти требования?

Я обеспокоен тем, что любой потенциальный выигрыш в точности представления (мы тратим большую часть формата с плавающей запятой в настоящее время, используя этот конкретный диапазон) будет полностью перевешен требованием дважды округлить при переходе от дробного представления к плавающему. укажи и вернись снова. В этом случае может потребоваться выполнить арифметику с использованием этого дробного представления напрямую, чтобы получить какую-либо выгоду от этого подхода. Любой совет на этот счет будет полезен?

1

Решение

Не использовать 2^16-1, использование 2^16, Да, у вас будет немного меньше точности и вы будете тратить впустую 0xFFFF, но вы гарантируете, что при преобразовании в плавающую точку нет потери точности. (Напротив, при преобразовании от плавающей запятой вы потеряете 8 бит точности мантиссала.)

Обратные преобразования между точностью могут вызвать проблемы с определенными операциями, в частности с постепенным суммированием чисел. Если это вообще возможно, обрабатывайте ваши значения с фиксированной точкой как «грязные» и не используйте их для дальнейших вычислений с плавающей точкой; предпочитаю пересчитывать из входных данных использование промежуточных результатов в форме с фиксированной запятой.

В качестве альтернативы используйте 24 бита. С этим представлением вы не потеряете точность ни в одном направлении, если ваши значения не уменьшатся (то есть, если они выше) 2^-24).

4

Другие решения

Разве 1 ​​/ х не будет плохо распределен в вашем диапазоне? 1/2 1/3 1/4 .. Вы не хотите представлять числа выше 1/2?

Подобные вещи делаются в Netcdf довольно много для кодирования данных для экономии места.

const double scale = 1.0/65536;
unsigned short x;

Любое число в x — это действительно x * шкала

Смотрите пример в NetCDF для более общего подхода с использованием масштаба и смещения: http://www.unidata.ucar.edu/software/thredds/current/netcdf-java/tutorial/NetcdfDataset.html

1

Взгляните на раздел «Значения упакованных данных» на этой странице:

https://www.unidata.ucar.edu/software/netcdf/docs/BestPractices.html#Packed%20Data%20Values

0
По вопросам рекламы [email protected]