Могу ли я хранить UInt32, Int32 и значение с плавающей запятой внутри double без потери информации?

1

Мне нужно сохранить значения UInt32, Int32 и float внутри переменной. Могу ли я использовать double без потери информации (например, потерять некоторые цифры в преобразовании) или мне нужно использовать произвольный класс точности?

Из моих текущих исследований, похоже, я могу, так как я могу хранить максимальное значение UInt32 без потери информации:

Assert.AreEqual(UInt32.MaxValue, Convert.ToUInt32(Convert.ToDouble(UInt32.MaxValue)));
  • Поэтому double должен поддерживать достаточное количество цифр, чтобы представлять все числа, меньшие или равные UInt32.MaxValue.
  • Int32 имеет в любом случае меньший диапазон значений, поэтому он также поддерживается.
  • Float также должен поддерживаться, поскольку он просто удваивается с меньшей точностью.

Я что-то пропустил?

  • 0
    Вы можете хранить их в Decimal формате: «Этот тип предоставляет методы, которые преобразуют десятичные значения в значения SByte, Int16, Int32, Int64, Byte, UInt16, UInt32 и UInt64 и обратно. Преобразования из этих целочисленных типов в десятичные являются расширяющими преобразованиями. которые никогда не теряют информацию и не создают исключений ".
Теги:
type-conversion
ieee-754
double
precision

1 ответ

12
Лучший ответ

Возможность хранить максимальное значение UInt32 без потери информации не обязательно означает, что вы сможете хранить все значения в UInt32 без потери информации - в конце концов, существует множество long значений, которые могут храниться в double даже если некоторые меньшие значения не могут. (2 62 можно легко сохранить точно в double, но 2 62 - 1 не могут, например.)

Тем не менее, вы в порядке - мантисса для double имеет длину в 52 бита, поэтому любое целое число с менее чем 52 битами может быть тривиально сохранено как значение * 2 0 (т.е. эффективный масштаб 0).

И да, значения float могут быть преобразованы в double без потери точности.

Однако обратите внимание, что это не означает, что 0.1f == 0.1d например, это просто означает, что (double) 0.1f является точно таким же числом, как 0.1f, в другом представлении.

Также стоит отметить, что Int32 не имеет меньшего диапазона, чем UInt32 - они оба имеют диапазон ровно 2 32 последовательных значения. Однако Int32 имеет меньшее "абсолютное" значение и способ, которым знак представлен в значениях с плавающей запятой, что имеет значение. Вам по-прежнему требуется 32 бита, чтобы сохранить абсолютное значение каждого Int32, потому что Int32.MinValue является -10000... 0000 в двоичном формате (всего 32 бита) или - (2 31 + 1).

Наконец, float не только double с меньшей точностью - он также получает меньший диапазон. Он имеет только 8 бит для экспоненты по сравнению с 11 в double. Таким образом, есть числа в пределах диапазона double которые находятся вне диапазона float, даже если у них нет значительных (двоичных) цифр.

  • 0
    «Любое целое число, содержащее менее 52 битов, может быть просто сохранено как значение * 2 ^ 0». Эта часть ответа слегка вводит в заблуждение, так как часть мантиссы хранит не целое число, а двоичную дробь между 1 и 2. Вам нужно используйте ненулевой показатель степени, чтобы переместить точку в правильное место при представлении целых чисел с плавающей точкой.
  • 0
    @JoanCharmant: Рассматривать как целое число или двоичную дробь - это просто вопрос другого взгляда на то, насколько он сдвинут. Я считаю, что проще рассматривать как целое число; YMMV. Я, конечно, думаю, что проще думать о значении, которое имеет целочисленный результат, как целое число, масштабированное до 0, чем как масштабированное двоичное дробное выражение ... вот почему я говорил об этом как об эффективном масштабе. Детали того, что представляет собой битовая комбинация показателя степени, наряду с нормализацией, здесь не имеют значения, за исключением разработки точной точки, в которой целые числа больше не могут быть точно представлены.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню