Вопрос по c# – Как сохранить число с плавающей точкой в 2 байта?

5

Да, я осведомлен о стандарте половинной точности IEEE-754, и да, я осведомлен о работе, проделанной в полевых условиях. Проще говоря, я пытаюсь сохранить простое число с плавающей запятой (например,52.1, или же1.25) всего за 2 байта.

Я пробовал некоторые реализации вДжава И вC # но они разрушают входное значение, декодируя другое число. Вы кормите в32.1 и после кодирования-декодирования вы получаете32.0985.

Есть ли ЛЮБОЙ способ хранить числа с плавающей запятой всего в 16 битах, не разрушая входное значение?

Спасибо большое.

Что сказал CodeInChaos - слово в слово ... David M
Какой диапазон чисел нужно кодировать и сколько значащих цифр у них есть? Рассмотрим десятичные числа с фиксированной или плавающей точкой. CodesInChaos
Двоичные плавающие точки не могут кодировать32.1 CodesInChaos
Можете ли вы хранить его какunsigned shortс некоторыми битами, используемыми для экспоненциальной части? Затем вы вручную конвертируете обратно из этого формата в обычную одинарную точностьfloat. Matthew
Вы должны быть более конкретными с вашей постановкой проблемы. Два байта могут представлять не более 65536 различных значений с плавающей запятой. Какие из них вы хотите? В худшем случае у вас может быть таблица «65536 значений с плавающей запятой, о которых я забочусь». и сделать двухбайтовое значение поиском. Raymond Chen

Ваш Ответ

6   ответов
6

но вы можете попробовать подход с фиксированной запятой.

Пример 8,8 с фиксированной точкой (8 до запятой, 8 после):

float value = 123.45;
ushort fixedIntValue = (ushort)(value * 256);

Таким образом, номер сохраняется следующим образом: XXXXXXXX, XXXXXXXX

и вы можете получить поплавок снова, используя это:

float value = fixedIntValue / 256f;
Ну, у тебя не может быть всего. Если вы хотите больше, вы можете попробовать 6,10 фиксированной точки или использовать 4 байта.
Это также имеет ограниченную точность. 52,1 становится 52,09765625.
молодец, очень помогло спасибо
Операция не запрашивает все, только чтобы вернуть точно такое же значение. Это не является необоснованным, если приемлем ограниченный диапазон. Вам просто нужно использовать другой подход, чем двоичное число с плавающей / фиксированной запятой.
1

ете просто закодировать свой «алфавит» из 11 символов в 4-битный код и хранить 4 х 4 бита в 2 байта.

да, что-то вроде двоичного десятичного кода будет работать нормально
5

float или жеdouble?

Вы бы лучше обслужили, храняshort и понимая, что, например, оно делится на 100, чтобы получить фактическое число? (Например, ваши примеры 52.1 и 1.25 могут быть сохранены как 5210 и 125) Я думаю, что это может быть лучшим решением для вас.

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

3

32.1 вany двоичный тип с плавающей точкой.

В одинарной точности самое близкое представимое значение - 32.099998. В полу-точности это, по-видимому, 32,0985.

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

Значение половинной точности использует 11 битов для значимого (старший бит 1 неявный). В интервале [32,64) 6 из этих битов используются для целочисленной части, оставляя 5 битов для дробной части. Таким образом, в этой области, [32,64), представимые значения в точности равны 1 / (2 ** 5) = 1/32. Ближайший к32.1 будет 32 + 3/32 (ок. 1027/32), что32.09375, Так что ваша "видимо" В конце концов, это не правильно. Я не знаю, откуда у Аскера есть его пример. Для значения с половинной точностью вы обычно выводите только 3 десятичных знака, поэтому"32.1" будет обычная точность.
2

не считая NaN и бесконечностей. Есть 65 536 значений для 16 битов в двух байтах. Ясно, что невозможно однозначно закодировать все значения с плавающей точкой в два байта.

Какие из них вы хотите закодировать?

Даже для одного значения знака и показателя степени (например, для всех значений с плавающей запятой от 4 до 8, не включая 8) существует 8 388 608 значений с плавающей запятой, поэтому вы даже не можете кодировать их в два байта.

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

6

ита для десятичной точки:

52.1 = 521 * 10 ^ -1 => 0x1521
1.25 = 125 * 10 ^ -2 => 0x2125

Это даст вам диапазон от 0,0000000000000001 до 999. Конечно, вы можете добавить смещение для десятичной точки, чтобы получить, например, диапазон от 0,0000000001 до 999000000.

Простая реализация из четырех бит используется для размещения десятичной точки, а остальные для значения. Без какой-либо проверки ошибок и не полностью проверены. (Могут возникнуть проблемы с точностью при использовании некоторых значений!= сравнивать двойники.)

public static short Encode(double value) {
  int cnt = 0;
  while (value != Math.Floor(value)) {
    value *= 10.0;
    cnt++;
  }
  return (short)((cnt << 12) + (int)value);
}

public static double Decode(short value) {
  int cnt = value >> 12;
  double result = value & 0xfff;
  while (cnt > 0) {
    result /= 10.0;
    cnt--;
  }
  return result;
}

Пример:

Console.WriteLine(Encode(52.1));
Console.WriteLine(Decode(4617));

Выход:

4617
52.1
Можете ли вы показать примеры функций с плавающей точкой для двоичного кодирования / декодирования? Мне очень жаль, но я действительно не понимаю, что происходит. Robinicks
@Geotarget: Вы можете сжать 4 цифры в два байта, но тогда у вас останется только два бита, чтобы описать, где находится десятичная точка. Для чисел с меньшим количеством цифр вы просто заполняете нулями, т.е.1.5 такой же как001.5 или же1.500.
В зависимости от необходимого диапазона, 3 цифры могут быть упакованы в 10 бит сDPD и оставить 6 битов для показателя степени (и подписать - если необходимо), диапазон будет больше, чем код выше, но, конечно, немного сложнее для кодирования / декодирования. Если требуется небольшой диапазон, тогда 14-битная мантисса обеспечит большую точность
@Geotarget: я добавил простую реализацию выше.
Большое спасибо, Гуффа! Очень круто. Robinicks

Похожие вопросы