Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > C/C++: Общие вопросы > промежуточная переменная изменяет результат |
Автор: borisbn 11.9.2012, 15:07 | ||||
Здравствуйте. Есть код
http://liveworkspace.org/code/56a6afbdb322b8112e351b2af54057a7 выводит
Вопрос. Почему почему выводит "zzz" и не выводит "xxx yyy" ? Спасибо. |
Автор: bsa 11.9.2012, 15:35 |
потому что x*y может быть равен 0,999999999999999999999999999999999999999999999999999 ![]() Поэтому все операции с действительными числами нужно производить через эпсилон. |
Автор: math64 11.9.2012, 16:22 | ||||
bsa, это не объясняет результата. Не помогает
добавляем
1. Получается: все промежуточные вычисления промежуточные ведутся в long double 2. По стандарту они должны идти в double - поэтому приведение к (double) игнорируется как бесполезная операция. 3. При присваивании переменной компилятор вынужден сделать приведение типа. И вот Вам результат ... |
Автор: math64 11.9.2012, 16:32 | ||||
Я же писал
По той же причине sizeof(x*y) равен sizeof(double). |
Автор: borisbn 11.9.2012, 16:32 | ||
ещё один момент: в 2008-й студии печатает
![]() Добавлено через 3 минуты и 52 секунды math64, я тут подумал... да.... похоже Вы правы. Господа, вам не кажется, что это - глюк компилятора ? |
Автор: Dem_max 11.9.2012, 17:30 |
Никаких глюков, два вариант могут существовать во вселенной |
Автор: math64 11.9.2012, 17:58 | ||
т.е. (float) не игнорируется. Ещё результат может зависеть от оптимизации. |
Автор: borisbn 11.9.2012, 18:00 |
У меня нет возможности посмотреть ассемблерный код, который генерит GCC. Если кто-нибудь не поленится и выложит сюда - буду благодарен. |
Автор: math64 11.9.2012, 18:08 | ||||
gcc 3.4.2 mingw
|
Автор: borisbn 11.9.2012, 21:17 | ||||||||
math64, спасибо.
это я, пожалуй, погорячился... ничего не понятно. все четыре сравнения кажутся одинаковыми =
=
= =
Добавлено через 1 минуту и 18 секунд я имел в виду: кто-нибудь может прокомментировать приведённый ассемблер ? |
Автор: math64 12.9.2012, 07:26 | ||||||||||||||
Используются разные ассемблерные команды.
нет сохранения результата умножения, за умножением сразу идёт сравнение
|
Автор: xvr 12.9.2012, 16:44 | ||||
Кстати, в 64х битной версии gcc печатает и zzz и xxx yyy И при включении уровня оптимизаций -O3 (для 32х битной) тоже печатает оба У меня на gcc (64 бита на Linux, версия 4.1.2) код немного получился другой, но суть та же Вариант с промежуточной переменной:
Без промежуточной переменной:
|
Автор: borisbn 12.9.2012, 21:24 |
жесть... всегда был уверен (не знаю почему), что 64 и 32 бита отличаются лишь работой с памятью, размером указателей и т.п., а операции с числами (int не берём) абсолютно одинаковые. Что ж... ошибался |
Автор: math64 12.9.2012, 21:24 | ||
Но в данном случае при уменьшении точности получаем более точный результат, о чем говорили в теме исползование double вместо float http://forum.vingrad.ru/forum/topic-355758.html Добавлено через 14 минут и 2 секунды
Если бы компилятор работал бы по стандарту - так и было бы. Т.е. после каждой операции нужно было бы выгружать результат во временную переменную и загружать в FPU снова. Но это потеря во времени, и как правило, потеря точности (данный пример, когда при округлении получаем более точный результат - исключение), поэтому проводится оптимизация. Пользователь от этого обычно не страдает. Вот в начале 80-х была другая ситуация. Машина - PDP-11/70, 16 разрядная. Компилятор Fortran-77. Нужно 32 разрядное целое. Пишем INTEGER*4 I Компилятор съедает, но I - 16 разрядная. Спрашиваем: Почему игнорируется *4? Ответ: потому что по стандарту фортрана INTEGER и INTEGER*4 - одно и то же. В: А почему тогда INTEGER 16 разрядный? О: Потому что процессор 16 разрядный Приходится использовать REAL |
Автор: borisbn 25.9.2012, 08:28 |
Кстати, вычитал в Twitter'е у Андрея Карпова (PVS-Studio) про этот сайт - http://assembly.ynh.io/ - позволяет посмотреть онлайн рез-т перевода Си/С++ кода в ассемблер |