Непоследовательное суммирование в C

Когда я запускаю следующую программу:

#include <stdio.h>
#include <math.h>

int main()
{
    double sum, increase;
    long amount, j;

    printf("sum = ");
    scanf("%lf", &sum);
    printf("increase = ");
    scanf("%lf", &increase);
    printf("amount = ");
    scanf("%ld", &amount);

    for (j = 1; j <= amount; j++)
    {
        sum += increase;
    }

    printf("%lf\n", sum);

    return 0;
}

Я получаю следующий ответ для этих значений:

MacBook:c benjamin$ ./test
sum = 234.4
increase = 0.000001
amount = 198038851
432.438851
MacBook:c benjamin$ ./test
sum = 234.4
increase = 0.000001
amount = 198038852
432.438851
MacBook:c benjamin$ ./test
sum = 234.4
increase = 0.000001
amount = 198038853
432.438852

где я увеличил переменную «количество» на 1 в каждом случае.

  • В первом суммирование дает то, что я ожидаю.
  • Во втором он на удивление дает такое же значение.
  • В третьем идет суммирование.

Почему это происходит?

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

Спасибо!


person Benjamin    schedule 21.05.2012    source источник
comment
Вы забыли главный вопрос?   -  person Malvolio    schedule 22.05.2012
comment
Числа с плавающей запятой имеют ограниченную точность, и я бы хотел, чтобы где-то была потеряна достаточная точность, чтобы сумма вышла одинаковой.   -  person Corbin    schedule 22.05.2012
comment
Что должен знать каждый программист об арифметике с плавающей запятой -- docs .oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html   -  person epatel    schedule 22.05.2012
comment
У меня возникает соблазн проголосовать за то, чтобы закрыть это как дубликат C - суммирование с двойной точностью Потому что это почти одно и то же. Единственная причина, по которой я этого не делаю, заключается в том, что код в связанном вопросе такого низкого качества, а ваш, по крайней мере, читабелен и лаконичен. :)   -  person Ken White    schedule 22.05.2012


Ответы (1)


Это проблема с форматированием, а не с номером. Если вы измените printf на

printf("%.12lf\n", sum);

результаты выглядят более похожими на то, что вы ожидали:

sum = increase = amount = 432.438851000198
sum = increase = amount = 432.438852000198
sum = increase = amount = 432.438853000198

«Мусор» в конце возникает из-за ограниченной точности чисел с плавающей запятой.

person Sergey Kalinichenko    schedule 21.05.2012
comment
Вот ваша слегка измененная программа по адресу ideone [ссылка]. - person Sergey Kalinichenko; 22.05.2012