Точность вычислений

Тема в разделе "WASM.BEGINNERS", создана пользователем Pahan, 7 янв 2010.

  1. Pahan

    Pahan New Member

    Публикаций:
    0
    Регистрация:
    10 янв 2009
    Сообщения:
    55
    Здравствуйте.
    Столкнулся на практике с такой ситуацией

    double a=0.31;
    double b=0.29;
    double c=0.02;
    if ((a-b)==c)
    cout<<"yes" <<endl;

    К моему удивлению, условие в скобках не выполняется. Подозреваю, что a-b=0.020000000000000453 и из-за этой погрешности результат сравнения - ЛОЖЬ,
    Буду благодарен, если кто-нибудь поделится своими мыслями относительно данной ситуации и способами,как можно добится результата ИСТИНА при подобном сравнении.
    Спасибо.
     
  2. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    Код (Text):
    1. if (x == y)
    заменять на
    Код (Text):
    1. static const double eps = 0.00000001;
    2.  
    3. if (x - y < eps)
     
  3. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    Код (Text):
    1. if (fabs(x - y) < eps)
    конечно.
     
  4. Pahan

    Pahan New Member

    Публикаций:
    0
    Регистрация:
    10 янв 2009
    Сообщения:
    55
    спасибо.
    такие вот они числа с плавающей запятой.
     
  5. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    n0name
    Погрешность имеет переменный размер.
     
  6. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    Booster
    ясное дело, что она зависит от того с какими числами оперирует кодописатель.
     
  7. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    n0name
    Кодописатели иногда работают не с константами.
     
  8. Pahan

    Pahan New Member

    Публикаций:
    0
    Регистрация:
    10 янв 2009
    Сообщения:
    55
    ну при вычислениях же можно полагать, что в любом случае это eps<=10^-6 допустим?
     
  9. Pahan

    Pahan New Member

    Публикаций:
    0
    Регистрация:
    10 янв 2009
    Сообщения:
    55
    для типа double
     
  10. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Pahan
    >что в любом случае это eps<=10^-6 допустим?
    Откуда такие цифры?
     
  11. Pahan

    Pahan New Member

    Публикаций:
    0
    Регистрация:
    10 янв 2009
    Сообщения:
    55
    Это вопрос был. Цифры наобум абсолютно. Ну должна же быть эта погрешность разумной.
    А вообще вот что нашел в инете еще по этому поводу, на одном из форумов:
    Код (Text):
    1. Просто числа хранятся в двоичном виде, по этому число 1.2 = 1 + 1/5 точно представить невозможно, можно только приближенно.
    2. Например в double точность мантиссы 52 бит, т.е. погрешность будет где-то +- 0.5 * 1/(2^52) ~ 1.110223e-16
     
  12. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Pahan
    Погнешность определяется разрядами, а не числом. Для разных чисел своя погрешность. Если взять большое или малое число, то ваше eps можно спускать в унитаз.
     
  13. AndreyMust19

    AndreyMust19 New Member

    Публикаций:
    0
    Регистрация:
    20 окт 2008
    Сообщения:
    714
    Равенство вещественных числ нельзя проверять из-за погрешности. Только "больше/меньше". Н-р, 0,6 по-моему в двоичном виде - бесконечная дробь.
     
  14. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    AndreyMust19
    >Равенство вещественных числ нельзя проверять из-за погрешности.
    Много чего нельзя, но нужно.
     
  15. Pahan

    Pahan New Member

    Публикаций:
    0
    Регистрация:
    10 янв 2009
    Сообщения:
    55
    Booster
    Какой тогда выход??
    Пусть погрешность определяется разрядом. Но тогда разве нельзявзять eps=10^-6 и использовать
    Код (Text):
    1. (fabs(x - y) < eps)
    считая это погрешностью в шестом разряде и для больших и для малых чисел?
     
  16. Pahan

    Pahan New Member

    Публикаций:
    0
    Регистрация:
    10 янв 2009
    Сообщения:
    55
    *шестой разряд после запятой имею ввиду
     
  17. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.035
    Pahan
    Если тебе так уж хочется сравнивать числа на равенство, то можешь создать свой класс Число_с_погрешностью, определить для него все нужные тебе операции, которые кроме самого числа будут еще вычислять и его погрешность.
     
  18. Pahan

    Pahan New Member

    Публикаций:
    0
    Регистрация:
    10 янв 2009
    Сообщения:
    55
    Если не сложно, объясните для тупых пожалуйста - почему нельзя взять некоторую универсально маленькую eps и использовать при всех операциях сравнения на равенство для переменных double?
     
  19. AndreyMust19

    AndreyMust19 New Member

    Публикаций:
    0
    Регистрация:
    20 окт 2008
    Сообщения:
    714
    Pahan
    Потому что с каждой математической операцией с double погрешность накапливается и eps надо увеличивать.
    Black_mirror
    Не мешало бы поставить счетчик при проведении каждой матоперации, чтобы увеличивать eps на разрядность мантиссы.
     
  20. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Pahan
    Погрешность это минимальное число в мантиссе. Но так как есть ещё порядок, то погрешность может иметь большой диапазон значений.