Сравнение с плавающей точкой в ​​C ++ - PullRequest
0 голосов
/ 21 сентября 2011

Предположим, у вас есть прямоугольник, нижняя левая точка 0,0 и верхняя правая точка 100,100.Теперь две линии пересекают прямоугольник.Я должен выяснить координаты точки пересечения.Я сделал это.Теперь проблема в том, что я не могу сказать, находится ли он внутри прямоугольника или нет.Я использовал двойное сравнение.Но я думаю, что это дает мне неправильный ответ.Предположим, что точка пересечения есть (x, y).Я использовал эту проверку для сравнения: if (x> = 0.0 && x <= 100.0 && y> = 0.0 && y <= 100.0).Что мне делать? </p>

//this function generates line
line genline( int x1 , int y1 , int x2 , int y2 ){
    line l ;
    l.A = y2 - y1 ;
    l.B = x1 - x2 ;
    l.C = l.A * x1 + l.B * y1 ;
    return l ;
}
//this function checks intersection
bool intersect( line m ,line n ) {
    int det = m.A * n.B - m.B * n.A ;
    if( det == 0 ){
        return false ;
    }
    else {
        double x = ( n.B * m.C - m.B * n.C ) / ( det * 1.0 ) ;
        double y = ( m.A * n.C - n.A * m.C ) / ( det * 1.0 ) ;        
        if( x >= 0.0 && x <= L && y >= 0.0 && y <= W ) { return true ; }
        else{ return false ; }
    }
}

РЕДАКТИРОВАТЬ: Обе линии растягиваются до бесконечности.

Ответы [ 3 ]

1 голос
/ 21 сентября 2011

Ваша математика выглядит правильно.Кстати, если линия что-то пересекает, она всегда внутри чего-то.

0 голосов
/ 28 марта 2012

Когда вы имеете дело с плавающей запятой (или двойной), проверка на равенство наивна и в крайних случаях будет неудачной. Каждое сравнение, которое вы проводите, должно относиться к «эпсилону», чрезвычайно малому количеству, которое не имеет значения. Если два числа находятся в эпсилоне друг для друга, то они считаются равными.

Например, вместо «if (a == b)» вам нужно:

bool isEqual(double a, double b, double epsilon = 1.E-10)
{    return fabs(a - b) <= epsilon;
}

Выберите подходящее значение для epsilon в зависимости от проблемной области.

0 голосов
/ 21 сентября 2011

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

Ваш алгоритм выглядит слишком упрощенным. Для более глубокого обсуждения этой темы вы можете посмотреть this и this . В этой статье из двух частей исследуется проблема нахождения пересечения двух линий с использованием чисел с плавающей точкой. Обратите внимание, что они касаются MATLAB, а не C ++, хотя это не меняет проблему, и алгоритмы легко переносятся на любой язык.

В зависимости от приложения, даже при умных уловках представление с плавающей точкой может не просто обрезать его для некоторых геометрических задач. CGAL - это библиотека C ++, предназначенная для вычислительной геометрии, которая решает подобные задачи. При необходимости он использует произвольную арифметику точности для обработки вырожденных случаев.

...