BitConverter.ToSingle усекает значения с плавающей запятой

#c# #floating-point

#c# #с плавающей запятой

Вопрос:

При преобразовании двоичных данных в значения с плавающей запятой с использованием String#unpack метода ruby я получаю следующие результаты:

 [0x7d, 0xe8, 0x80, 0xc5].map(amp;:chr).join.unpack('e')[0]
# => -4125.06103515625
  

Это считается правильным результатом.

Используя BitConverter.ToSingle метод C #, я получаю следующий результат:

 var firstVal = BitConverter.ToSingle(new byte[] {0x7d, 0xe8, 0x80, 0xc5}, 0);
// firstVal: -4125.061
  

Таким образом, кажется, что значение каким-то образом усекается.
Есть ли способ извлечь правильное значение (как в ruby примере) из двоичного представления?

Комментарии:

1. Как вы печатаете значение?

2. Console.WriteLine(((double)firstVal).ToString("R")); выводит то же значение, что и ruby.

Ответ №1:

Насколько я помню, Ruby имеет только один тип с плавающей запятой, и это float с двойной точностью. Таким образом, тип значения вашего выражения ruby — это значение с плавающей запятой двойной точности, аналог которого в C # — «double». Так что, если вы хотите получить точно такое же число, вы можете сделать это (но я не уверен, что это действительно имеет смысл, см. Комментарий @xanatos):

 var firstVal = (double) BitConverter.ToSingle(new byte[] {0x7d, 0xe8, 0x80, 0xc5}, 0); 
// firstVal is -4125.06103515625
  

Комментарии:

1. Нужно задаться вопросом, почему в документации указано, что строка 'e' формата будет возвращать число с плавающей запятой одинарной точности… с документацией проблемы снова и снова…

2. @InBetween Я думаю, что в нем указано, что возвращаемое значение равно Float (единственный тип ruby с плавающей запятой), но формат «e» означает, что массив байтов следует рассматривать как содержащий одинарную точность с плавающей запятой (поэтому имеет 4 байта, а не 8, как double)

3. о, лол. Я связал «строку формата» с выводом, а не с вводом. Думаю, это имеет смысл…