проблема с double

Тема в разделе "WASM.BEGINNERS", создана пользователем Codeblight, 7 май 2006.

  1. Codeblight

    Codeblight New Member

    Публикаций:
    0
    Регистрация:
    17 окт 2005
    Сообщения:
    60
    Адрес:
    Russia
    Люди добрые, просвятите ламера 8)

    Есть такая проблема - пишу на VC, есть класс МатрицА... вообщем не я его писал, но он много чего может. И тут случилась проблема - при использовании его (при попытке посчитать обратную матрицу) вычисляемый определитель у тестовой матрицы должен получиться 0 (в Excel 0), а (благодаря видимо даблам) он получается 1,41... * 10^-28... т.е. почти 0, но VC сравнить с 0 его не может *) т.к. он для него не 0. Все вот везде пишут - "сравнивайте с каким-нибудь промежутком..." Собственно вопрос - а с чем мне сравнивать ?) т.е. после скольки знаков после запятой можно считать нулем ?
     
  2. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Codeblight

    > "после скольки знаков после запятой можно считать нулем ?"

    > "благодаря видимо даблам"

    Точнее сказать благодаря ограниченной точности вычислений FPU. Наглядный пример: 1-(1/3)*3 на бумаге будет = 0, а на компютере 1/3 = 0.33(3), умножая на 3 получаем 0.99(9) и в итоге результат будет не 0, а 0.000_01 - единичка младшего значащего разряда мантиссы (при бОльшем числе операций погрешность может нарастать). Поэтому в FPU все вычисления производятся с бОльшей точностью (extended или double) и затем результат округляется до меньшей точности (double или single) и при округлении погрешность "исчезает".

    Еще одна особенность FPU: простые операции типа сложения\вычитания\умножения всегда выполняются с максимальной точностью (extended), а вот точность вычисления медленных операций типа деления и извлечения корня задается управляющим словом FPU - чем точнее, тем дольше. Поэтому если из соображений оптимизации по скорости компилер использует точность вычислений double (а не extended), то ес-но после деления или корня результат double м.б. "неточным". Выход - либо увеличить точность вычислений до extended, либо при сравнении с 0 загрублять результат (это всегда надежнее). Для double это "загрубление" должно быть не меньше младшего значащего бита мантиссы, т.е. 2^(-53) ~ 10^(-16) - это соответсвует точности представления чисел в формате double, о чем можно прочитать как в IA-32, так и в описании типов любого компилятора от C++ до VB :))
     
  3. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.347
    Codeblight



    другими словами, если меньше 0.000000000001 - считай нулем :)