Как литералы типа float / double хранятся в скомпилированных. NET файлах DLL? - PullRequest
1 голос
/ 02 апреля 2020

Мое приложение должно выдавать одинаковые результаты c на всех машинах. Я понимаю, что float / double math в C# не является детерминированным c, но как насчет двоичного представления литеральных значений?

float x = 1.23f;

Как 1.23f будет храниться в скомпилированном файле DLL? Как двоичное представление 32-битного формата IEEE-754 с плавающей точкой? Или как какое-то промежуточное представление, которое потребует преобразования в IEEE-754 с помощью джиттера на целевой машине (потенциальный источник неопределенности)?

Я понимаю, почему операции с плавающей запятой в C# не являются deterministi c. Я спрашиваю ТОЛЬКО, является ли двоичное представление литералов детерминированным c. Пожалуйста, никаких ответов о детерминизме с плавающей точкой в ​​целом.

Ответы [ 2 ]

2 голосов
/ 02 апреля 2020

Они хранятся в формате IEEE 754.

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

Например, float x = 1.23f; сгенерирует:

IL_0000:  /* 22   | A4709D3F         */ ldc.r4     1.23

(Обратите внимание, что это хранится в формате с прямым порядком байтов на платформах Intel.)

0 голосов
/ 02 апреля 2020

По этой причине был введен десятичный тип. Проверьте это в официальной документации Microsoft здесь. https://docs.microsoft.com/en-us/dotnet/api/system.decimal?view=netframework-4.8

Десятичное число - это значение с плавающей запятой, которое состоит из знака, числового значения c, где каждое значение di git в диапазоне значений от От 0 до 9, и масштабный коэффициент, который указывает положение плавающей десятичной запятой, которая разделяет целую и дробную части числового значения c.

Двоичное представление десятичного значения состоит из 1- битовый знак, 96-разрядное целое число и коэффициент масштабирования, используемый для деления 96-разрядного целого числа и указания, какая его часть является десятичной дробью. Коэффициент масштабирования - это неявное число 10, возведенное в степень в диапазоне от 0 до 28. Следовательно, двоичное представление десятичного значения в форме, ((от -296 до 296) / 10 (от 0 до 28)), где - ( 296-1) равен MinValue, а 296-1 равен MaxValue. Для получения дополнительной информации о двоичном представлении десятичных значений и примере см. Конструктор Decimal (Int32 []) и метод GetBits.

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

...