Форум программистов, компьютерный форум CyberForum.ru

Ошибка в переменной типа double - C++

Восстановить пароль Регистрация
 
nill
8 / 8 / 0
Регистрация: 16.08.2009
Сообщений: 417
23.12.2009, 07:03     Ошибка в переменной типа double #1
Не могу понять в чем проблема
делаю такие вычисления

C++
1
2
3
4
5
6
7
8
9
10
11
#include <iomanip>
summ5=0;
summ5+=((double) 1/1035*2);
summ5+=((double) 1/1035*15);
summ5+=((double) 1/1035*108);
summ5+=((double) 1/1035*405);
summ5+=((double) 1/1035*351);
myfile << std::fixed << std::setprecision(20) << "summ5 "<< summ5<<"\n";
 
summ6=((double) 881/1035);
myfile << std::fixed << std::setprecision(20) << "summ6 "<< summ6<<"\n";
получаю summ5 равно 0.85120772946859913000
а summ6 равно 0.85120772946859902000


хотя summ5 должно быть равно summ6 так как (2+15+108+405+351=881)

если summ5 состоит из большего количества элементов то разница еще больше
а учитывая что таких элементов в программе может быть очень и очень много я боюсь что результаты вычислений будут совсем не корректными

В чем проблема ? ведь чисто математически числа не могут быть разными
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Yurii_74
paladin
 Аватар для Yurii_74
279 / 179 / 3
Регистрация: 25.02.2009
Сообщений: 592
23.12.2009, 07:56     Ошибка в переменной типа double #2
Проблема в том, что даже double дискретен. Если уж приходится складывать ряд, то нужно проделывать это от меньшего к большему (иногда желательно сначала подсчитать промежуточные суммы очень малых элементов). В вашем случае 15 знаков совпадают. Для double 16 значащих десятичных знаков - предел.
И именно из-за этого для проверки разности двух (вычисляемых) чисел с нулем они сравниваются по модулю с некоторым небольшим (относительно их самих) числом.

Wikipedia о double
TanT
эволюционирую потихоньку
 Аватар для TanT
464 / 462 / 43
Регистрация: 30.06.2009
Сообщений: 1,399
23.12.2009, 08:22     Ошибка в переменной типа double #3
Цитата Сообщение от nill Посмотреть сообщение
В чем проблема ? ведь чисто математически числа не могут быть разными
накапливается ошибка округления, что здесь необычного?
может нужно поискать пути её уменьшения за счёт иного способа вычислений компонент, например вынести общий делитель
nill
8 / 8 / 0
Регистрация: 16.08.2009
Сообщений: 417
23.12.2009, 08:28  [ТС]     Ошибка в переменной типа double #4
Yurii_74,
сложил от меньшего к большему и цифры ПОЛНОСТЬЮ сошлись
придеться делать сортировку а это думаю не очень хорошо скажеться на производительности

непонял что значит подсчитать промежуточные суммы очень малых элементов ?
Yurii_74
paladin
 Аватар для Yurii_74
279 / 179 / 3
Регистрация: 25.02.2009
Сообщений: 592
23.12.2009, 08:41     Ошибка в переменной типа double #5
Пусть у тебя есть числа 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.1, 0.2, 100.
Сначала складываем 1 со 2, 3 с 4, 5 с 6, 7 с 8:
0.002, 0.002, 0.002, 0.002, 0.1, 0.2, 100.
0.004, 0.004, 0.1, 0.2, 100.
0.008, 0.1, 0.2, 100.
Затем уже по порядку.
Делается это для выравнивания порядка складываемых элементов (попробуй прибавить 10^-6 к 10^15).
И как сказал TanT, лучше сначала подсчитать сумму в int'ах. Если такая возможность вообще есть.
nill
8 / 8 / 0
Регистрация: 16.08.2009
Сообщений: 417
23.12.2009, 08:47  [ТС]     Ошибка в переменной типа double #6
точно как это я сразу не додумался
просто постчитал сумму интов и делаю все вычисления за пределами цикла и все сходиться


Yurii_74,
TanT, спасибо еще раз
Yandex
Объявления
23.12.2009, 08:47     Ошибка в переменной типа double
Ответ Создать тему
Опции темы

Текущее время: 20:23. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru