Почему разница в вычислениях/кастинге между (long)z и (long)(x+y)?
Тестирую на .NET Framework 4.5.2 x86
float test1 = 1.3F,
test2 = 5.2F;
float i2_float = test1 * 100,
i3_float = test2 * 100;
long i1 = (long)i2_float;
long i2 = (long)i3_float;
Для первого варианта получаю следующие значения: i1=130, i2=520
float test1 = 1.3F,
test2 = 5.2F;
long i1 = (long)(test1 * 100);
long i2 = (long)(test2 * 100);
Для второго получаю следующие значения: i1=129, i2=519
Почему получаю разные результаты для i1/i2 если результат операций test * 100 в обеих вариантах равен float и явно кастится в long?
Ответы (1 шт):
Чтобы понять, надо вспомнить, что float - это число с плавающей точкой, а следовательно все операции, производимые с ним, могут иметь погрешность в рамках его уровня точности.
Наверняка воспроизводимый код у меня не получилось сделать, чтобы показать, что там внутри, но по факту, там что-то типа 1.29999999998 вместо 1.3, которое вы умножаете на 100, затем приведением к long отбрасываете дробную часть, и получается 129. То же самое для второго числа.
Почему float i2_float = test1 * 100 работает: потому что компилятор умный и он решил оптимизировать ваше умножение как работу с константами, то есть ваш код скомпилируется во что-то типа long i1 = 130L; и никаких упоминаний в скомпилированном коде о float не будет. То есть финальное значение до какой-то степени будет вычислено на этапе компиляции. Точно так же как если бы у вас было const float test1 = 1.3F.
Почему разница результата в двух примерах: компилятор в .NET 4.x недостаточно умный, чтобы оптимизировать оба примера, у него хватило алгоритмов только на 1 из двух, а вот компилятор в .NET 6 - уже умнее и смог распознать и оптимизировать оба случая.