Я пытаюсь вычислить значение машинного эпсилона для двойников и чисел с плавающей запятой в C ++ как часть школьного задания. Я использую Cygwin в Windows 7, 64-битная, вот код:
#include <iostream>
int main() {
double epsilon = 1;
while(1 + epsilon > 1)
epsilon = epsilon / 2;
epsilon = 2*epsilon;
std::cout << epsilon << std::endl;
float epsilon_f = 1;
while(1 + epsilon_f > 1)
epsilon_f = epsilon_f / 2;
epsilon_f = 2*epsilon_f;
std::cout << epsilon_f << std::endl;
return 1;
}
Когда я запускаю код, я получаю 1.0842e-019 для обоих значений. Я посмотрел вверх и должен был получить 2.22e-16 для двойного и 1.19e-07 для значения с плавающей точкой. Когда я бегу точный тот же код на Macbook, код возвращает правильные значения. Что может быть причиной расхождений на моем компьютере с Windows?
Регистры с плавающей точкой процессора обычно содержат 80 бит, и похоже, что компилятор Cygwin решает выполнять вычисления цикла полностью в регистрах (только обрезая результат до 32/64 бит при печати результатов).
Как указывает @Potatoswatter, это совершенно законно для компилятора, и ваша программа на самом деле демонстрирует неопределенное поведение, поскольку предполагает, что является предел точности. Поскольку поведение не определено, компилятор может преобразовать вашу программу во что угодно (включая ту, которая удаляет все ваши файлы, но, к счастью, это не распространенное решение …)
Постскриптум Добро пожаловать в StackOverflow и благодарность за вопрос, который (если вы прочитаете концепции в ответах), вероятно, заставит вас узнать больше об архитектуре процессора и компиляторах, чем кто-либо в вашем классе! 🙂