Я заметил интересное поведение с округлением / усечением с плавающей точкой компилятором C #.А именно, когда литерал с плавающей запятой выходит за пределы гарантированного представимого диапазона (7 десятичных цифр), то а) явное приведение результата с плавающей запятой к плавающей запятой (семантически ненужная операция) и б) сохранение промежуточных результатов вычислений в локальной переменной и изменяют вывод.Пример:
using System;
class Program
{
static void Main()
{
float f = 2.0499999f;
var a = f * 100f;
var b = (int) (f * 100f);
var c = (int) (float) (f * 100f);
var d = (int) a;
var e = (int) (float) a;
Console.WriteLine(a);
Console.WriteLine(b);
Console.WriteLine(c);
Console.WriteLine(d);
Console.WriteLine(e);
}
}
Вывод:
205
204
205
205
205
В отладочной сборке JITted на моем компьютере b вычисляется следующим образом:
var b = (int) (f * 100f);
0000005a fld dword ptr [ebp-3Ch]
0000005d fmul dword ptr ds:[035E1648h]
00000063 fstp qword ptr [ebp-5Ch]
00000066 movsd xmm0,mmword ptr [ebp-5Ch]
0000006b cvttsd2si eax,xmm0
0000006f mov dword ptr [ebp-44h],eax
, тогда какd вычисляется как
var d = (int) a;
00000096 fld dword ptr [ebp-40h]
00000099 fstp qword ptr [ebp-5Ch]
0000009c movsd xmm0,mmword ptr [ebp-5Ch]
000000a1 cvttsd2si eax,xmm0
000000a5 mov dword ptr [ebp-4Ch],eax
Наконец, мой вопрос: почему вторая строка вывода отличается от четвертой?Имеет ли это дополнительный смысл такое различие?Также обратите внимание, что если последняя (уже непредставленная) цифра из числа с плавающей точкой f будет удалена или даже уменьшена, все «встанет на свои места».