C #: неправильный результат при преобразовании выражения с плавающей точкой в ​​int - PullRequest
2 голосов
/ 23 апреля 2019

Возьмите следующий код:

float a = 100.0f;
float b = 0.05f;

Если я хочу преобразовать результат деления между a и b в целое число, я могу сделать это с помощью следующего кода:

float c = a / (b * 1000.0f); // c = 2f
int res = (int)c; // res = 2

Но я хочу уменьшить количество строк кода, поэтому я предпочитаю использовать этот код:

int res = (int)(a / (b * 1000.0f)); // Here we are --> res = 1 !

Почему с последним кодом я получаю res = 1 вместо res = 2?

1 Ответ

3 голосов
/ 23 апреля 2019

Компилятор использует дополнительную точность при вычислении некоторых выражений.В спецификации языка C # пункт 9.3.7 позволяет реализации использовать большую точность в выражении с плавающей запятой, чем тип результата:

Могут выполняться операции с плавающей запятойс большей точностью, чем тип результата операции.

Обратите внимание, что значение .05f равно 0,0500000007450580596923828125.Когда .05f * 1000.0f вычисляется с точностью float, результат равен 50 из-за округления.Однако, когда он вычисляется с точностью double или выше, результатом будет 50,0000007450580596923828125.Тогда деление 100 на это с точностью double дает 1.999999970197678056393897350062616169452667236328125.Когда это значение преобразуется в int, результат равен 1.

В float c = a / (b * 1000.0f); результат деления преобразуется в float.Даже если деление вычисляется с точностью double и выдает 1.999999970197678056393897350062616169452667236328125, это значение становится равным 2 при округлении до float, поэтому c устанавливается равным 2.

В int res = (int)(a / (b * 1000.0f));, результатделение не конвертируется в float.Если компилятор вычисляет его с точностью double, результат равен 1.999999970197678056393897350062616169452667236328125, и выполняется преобразование, которое дает 1.

...