Как правильно представить большое числовое значение в float без потери точности - PullRequest
1 голос
/ 08 ноября 2019

У меня есть некоторые значения, прочитанные как string из файла, которые больше 2^23. при преобразовании их в float значения меняются из-за потери точности .

double d  = 50000167;
float f = (float)d;
f gives a value of 50000168.0

Я не могу использовать double из-за конструктивных ограничений. Как выполнить работу с помощью поплавков

Ответы [ 2 ]

0 голосов
/ 08 ноября 2019

Возможно, вам удастся сойти с рук, сделав Hacky As Fuck, для имитации 40-битного числа с плавающей запятой, которое вы затем преобразовали бы в двойное число, когда вам нужно было использовать его, а затем разбили его обратно в число с дополнительным байтомточности хранится вдоль него.

Вот макет двойника:

enter image description here

По сравнению с макетом поплавка:

enter image description here

Таким образом, если добавить один байт, вы получите точность от 23 до 31 бита.

Вам нужно будет принять исходное значениекак двойные и маскирующие биты 24-31, записывая их в ваш дополнительный байт, который вы сохраните вместе с вашим числом. Чтобы переключиться обратно, вы должны преобразовать число с плавающей запятой обратно в двойное число, а затем установить биты дроби этого двойного числа 24-31 из вашего дополнительного байта памяти.

Согласно комментарию @ drescherjm, это даст вам около 10 цифр. точности, когда этому конкретному случаю нужно только 8.

Во всем этом есть большой жирный уродливый нюанс. Если вы объявляете структуру:

struct ugly40BitFloatHackityHackHack {
    float mostOfTheValue;
    BYTE extra8BitsOfPrecision;
};

... Компилятор часто резервирует 64 бита (размер двойного) из-за «выравнивания памяти». По сути, компьютер работает быстрее, когда переменные правильно расположены в памяти, поэтому они могут напрямую отображаться в регистры ЦП ... на 32/64 / любых битовых границах. Существуют способы управления выравниванием памяти (или «упаковать» все как можно плотнее).

А-а. Перечитывая свой вопрос прямо сейчас, вы не беспокоитесь о «хранилище», а о некоторых произвольных ограничениях дизайна. Я предполагаю, что это либо для класса, либо ваш босс - ископаемое восхождение к тем временам, когда самое дорогое, что мог сделать процессор, это математика с плавающей запятой. В наши дни процессоры тратят слишком много времени на ожидание памяти. «Back In The Day» операция с плавающей запятой могла занимать 20-40 циклов, а удвоения были даже дороже, чем поплавки. В наши дни операции с плавающей запятой дешевы (около 1 цикла) или около того, а доступ к памяти стоит дороже (потеря кэша может стоить около 100-200 циклов ... связанные списки могут заставить ваш процессор плакатькровь).

Если ваш начальник беспокоится об эффективности, используйте профилировщик. Не угадайНе применяйте устаревшую десятилетия "мудрости". Используйте профилировщик .

И если это действительно просто классное задание, это может быть просто способ научить вас ограничению точности в float против double. Поздравь своего учителя: это сработало.

0 голосов
/ 08 ноября 2019

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

Вы, вероятно, должны либо использовать арифметику произвольной точности, либо уменьшить свои ожидания относительно точности.

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