Ответ 1
Проблема зависит от этого выражения:
bool bLarger2 = (a*c)<b;
Я просмотрел код, созданный в VS2008, не имея VS2010. Для 64-битного кода:
000000013FD51100 movss xmm1,dword ptr [a] 000000013FD51106 mulss xmm1,dword ptr [c] 000000013FD5110C movss xmm0,dword ptr [b] 000000013FD51112 comiss xmm0,xmm1
Для 32-битного кода:
00FC14DC fld dword ptr [a] 00FC14DF fmul dword ptr [c] 00FC14E2 fld dword ptr [b] 00FC14E5 fcompp
Итак, до 32 бит вычисление выполняется в блоке x87, а под 64 бит выполняется блоком x64.
И здесь разница заключается в том, что все операции x87 выполняются до более высокой, чем одинарная. По умолчанию вычисления выполняются с двойной точностью. С другой стороны, операции SSE-блока являются чистыми вычислениями с одной точностью.
Вы можете убедить 32-разрядную единицу выполнить все вычисления с точностью до одной точности:
_controlfp(_PC_24, _MCW_PC);
Когда вы добавляете это в свою 32-битную программу, вы обнаружите, что логические значения равны false.
Существует принципиальное различие в том, как работают модули с плавающей точкой x87 и SSE. Блок x87 использует одни и те же инструкции для одиночных и двойных типов точности. Данные загружаются в регистры в стеке x90 FPU, и эти регистры всегда имеют длину в 10 байт. Вы можете управлять точностью с помощью управляющего слова с плавающей запятой. Но инструкции, которые компилятор пишет, не знают этого состояния.
С другой стороны, модуль SSE использует разные инструкции для операций с одинарной и двойной точностью. Это означает, что компилятор может испускать код, который полностью контролирует точность вычисления.
Итак, единица x87 - плохой парень. Возможно, вы попытаетесь убедить своего компилятора испустить инструкции SSE даже для 32-битных целей. И, конечно, когда я скомпилировал ваш код под VS2013, я обнаружил, что как 32, так и 64-битные цели выбрали инструкции SSE.