C # Преобразование Double в Float теряет столько точности, почему? - PullRequest
0 голосов
/ 06 января 2019

Когда я отлаживаю свою программу с помощью Visual Studio;

Когда я преобразовываю двойную переменную "91.151497095188446" в число с плавающей запятой, используя

(float)double_variable

Я вижу результирующую переменную с плавающей запятой "91.1515".

Почему я теряю столько точности? Нужно ли использовать другой тип данных?

Ответы [ 2 ]

0 голосов
/ 07 января 2019

C # и многие другие языки используют IEEE 754 в качестве спецификации для своих типов данных с плавающей точкой. Числа с плавающей запятой выражаются в виде значения и экспоненты, аналогично тому, как десятичное число в научной записи выражается как

1.234567890 x 10^12
     ^          ^
  mantissa   exponent

Я не буду вдаваться в подробности (статья в Википедии разбирается в этом лучше, чем я), но IEEE 754 указывает, что :

  • для 32-разрядного числа с плавающей запятой, такого как тип данных C # float, имеет 24-битную точность для значимости и 8-битную для показателя степени.

  • для 64-битного числа с плавающей запятой, такого как тип данных C # double, имеет 53 бита для значимости и 11 бит для показателя степени.

Поскольку float имеет только 24 бит точности, он может выражать только 7-8 цифр точности. И наоборот, double имеет точность 53 бит , поэтому имеет точность 15-16 цифр точности.

Как было сказано в комментариях, если вы не хотите терять точность, не переходите от double (всего 64 бита) к float (всего 32 бита). В зависимости от вашего приложения вы, возможно, можете использовать тип данных decimal, который имеет 28-29 десятичных цифр точности, но будет иметь штрафы, потому что (a) вычисления с ним медленнее, чем для double или float, и (b) обычно он гораздо меньше поддерживается внешними библиотеками.


Обратите внимание, что вы говорите о 91.15149709518846, который на самом деле будет интерпретироваться компилятором как 91.1514970951884 - см., Например, this :

double value = 91.151497095188446;
Console.WriteLine(value);
// prints 91.1514970951884
0 голосов
/ 06 января 2019

Подробное объяснение вы найдете здесь: https://stackoverflow.com/a/2386882/10863059

По сути, float занимает меньше места в памяти (4 байта) по сравнению с double (8 байтов), но это только одна часть истории.

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