#c# #wpf #linq #double
#c# #wpf #linq #двойной
Вопрос:
У меня есть функция, в которой я пытаюсь найти точку соответствия между 2 коллекциями по 4 точки в каждой, но иногда функция сообщает, что коллекции не имеют общей точки, хотя в отладчике я вижу, что они есть. неужели отладчик не показывает мне полную точность точек, поэтому я не вижу разницы? или здесь происходит что-то еще? виноват код:
public static Point CorrectForAllowedDrawArea(Point previousDisplayLocation, Point newDisplayLocation, Rect displayLimitedArea, Rect newBoundingBox)
{
// get area that encloses both rectangles
Rect enclosingRect = Rect.Union(displayLimitedArea, newBoundingBox);
// get corners of outer rectangle, index matters for getting opposite corner
var outsideCorners = new[] { enclosingRect.TopLeft, enclosingRect.TopRight, enclosingRect.BottomRight, enclosingRect.BottomLeft }.ToList();
// get corners of inner rectangle
var insideCorners = new[] { displayLimitedArea.TopLeft, displayLimitedArea.TopRight, displayLimitedArea.BottomRight, displayLimitedArea.BottomLeft }.ToList();
// get the first found corner that both rectangles share
Point sharedCorner = outsideCorners.FirstOrDefault((corner) => insideCorners.Contains(corner));
// find the index of the opposite corner
int oppositeCornerIndex = (outsideCorners.IndexOf(sharedCorner) 2) % 4;
в последней строке для ‘sharedCorner’ иногда устанавливается значение по умолчанию (точка), хотя обе коллекции точек, по-видимому, разделяют 1 точку.
РЕДАКТИРОВАТЬ: я должен упомянуть, что если я помещу отладчик обратно в начало функции и перезапущу его, он все равно не найдет точку соответствия. Я должен также упомянуть, что эта функция использует класс Point системы.Пространство имен Windows, а не системы.Пространство имен рисования! Спасибо, что указали мне на это в комментариях.
Комментарии:
1. Где-то вы полагаетесь на Equals() для double или float здесь. И это приведет к сбою при наличии ошибок округления.
2. @HenkHolterman: Я тоже это подозревал, но, похоже, используются только целые
Point
числа, а неPointF
.3. @Leppie: правильно, если это из System. Рисование. Из вопроса не совсем ясно. Обратите внимание на «полную точность точек»
4. спасибо, что указали на это, я соответствующим образом отредактировал вопрос
Ответ №1:
Нам действительно нужно посмотреть, что такое определение insideCorners.Contains(corner)
, но я подозреваю, что ваша проблема связана с присущими неточностями с числами с плавающей запятой.
Вы не можете сравнить два значения с плавающей запятой, подобные этому:
if (a == b)
{
// Values are equal
}
особенно, если либо a
или b
являются вычисляемыми значениями.
Вам нужно будет реализовать что-то вроде:
if (Math.Abs(a - b) < some_small_value)
{
// Values are equal
}
Комментарии:
1. вы правы, я изменил его на Point sharedCorner = outsideCorners . FirstOrDefault((outsideCorner) => insideCorners.Exists((insideCorner) => Math.Abs((insideCorner — outsideCorner) . Длина) < Math.Pow(10, -10))); который проверяет равенство с использованием порога допуска, и это работает, но также очень медленно, спасибо, что указали мне в этом направлении