2015-03-12 4 views
0

я играл с следующим фрагментом кодаПочему fmod производит разные результаты?

#include <iostream> 
#include <cmath> 
#include <cstdio> 
using namespace std; 

int main() { 
    double speed = 60.0; 
    double distance; 
    int a, b, c; 
    scanf("%lf %d %d %d", &distance, &a, &b, &c); 

    cout << distance << " " << a << " " << b << " " << c << endl; 
    cout << (fmod((distance*3600)/speed, (a + b + c))) << endl; 
    return 0; 
} 

и заметил, что для следующего входа

15.1 1 1 1 

производит это (неправильно?) Результат на моей машине

15.1 1 1 1 
3 

Но, похоже, этот результат получается на ideone (http://ideone.com/mwMalv)

15.1 1 1 1 
0 

Я понимаю, что «0,1» (в «15) не могут быть представлены точно как двойной

http://www.exploringbinary.com/why-0-point-1-does-not-exist-in-floating-point/

но другие, которые управляют этим кодом с GCC 4.8.2 и получить то, что произведенный на идеоне.

Я бегу Ubuntu 14.04.2 LTS Desktop (32-bit) на VMware 6.0.5 build-2443746 с gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1).

Что дает? Почему fmod ведут себя по-другому на моей машине, чем на других (учитывая то же, что и у компилятора)?

ответ

1

Ваши расчеты выходят примерно до fmod(906, 3). Однако 906 может быть 905.9999999999998532 или что-то, из-за ошибок со значениями, которые не являются точно представимыми.

Результат fmod с последним, чем 3 даст 2.999999999999999998532, который будет отображаться как 3 когда округляется до точности по умолчанию 6.

Чтобы узнать, что происходит подробно, сделайте << setprecision(30) в своих записях cout.

Также может быть освещено, чтобы проверить выход сборки, сгенерированный в каждом случае. Возможно, компиляторы делают разные вещи; или, возможно, они делают то же самое, и FPU отличается.

Например, результат 906 может быть выполнен даже в более высокой точности, чем double. Изменение кода для его хранения в double, прежде чем перейти к fmod, может или не может иметь значение.

+0

Спасибо, что поделились своими подробными мыслями по этому вопросу. Я сделал так, как вы предложили, и поставил '<< setprecision (30)' и получил '2.99999999999997868371792719699'. Я также изменил код для хранения вычислений в 'double' _before_, переходящем в' fmod', но получивший тот же результат. Однако я не уверен, как проверить сборку. – aLearner

+0

в компиляции gcc с переключателем '-S'. , он выведет сборку –

Смежные вопросы