2013-05-08 4 views
5

У меня есть странная проблема, и у меня нет подсказки, чтобы отслеживать причину. Я попытаюсь четко описать свою проблему.IComparer issue

Я класс RTree, в этом классе, я хочу, чтобы сравнить два rectanlge (здесь я назвал конверт, он содержит Minx, MinY, Maxx, MAXY), поэтому у нас есть класс компаратора следующим образом:

private class AnonymousXComparerImpl : IComparer 
{ 
    public AnonymousXComparerImpl() 
    { } 

    public int Compare(object o1, object o2) 
    { 
     IEnvelope ea = (IEnvelope)((IBoundable)o1).Bounds; 
     IEnvelope eb = (IEnvelope)((IBoundable)o2).Bounds; 
     double a = (ea.MinX + ea.MaxX)/2d; 
     double b = (eb.MinX + eb.MaxX)/2d; 
     return a > b ? 1 : a < b ? -1 : 0; 
    } 
} 

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

Невозможно разобраться, так как метод IComparer.Compare() возвращает противоречивые результаты. Либо значение не сравнивается с самим собой, , либо одно значение, несколько по сравнению с другим значением, дает разные результаты .

sortedChildBoundables.Sort(new AnonymousXComparerImpl()); 

Вот странная часть. Эта ошибка возникает только в .net 4.0, которая не устанавливает VistualStudio. Если на машине установлены VS или .net 4.5, эта проблема не может повториться повторно.

В этом случае я не могу понять, почему это происходит. Будет здорово, если у вас есть какой-либо опыт по отладке такого рода вопросов, я ценю.

Спасибо, Говард

+0

Единственное, что я могу придумать здесь, это проблемы с плавающей запятой, означающие, что равенство не совсем подходит для одних и тех же предметов, не знаю, почему это было бы специфично для v4. Вы пытались обеспечить уровень округления? –

+0

Попробуйте использовать тип данных 'decimal' вместо двойного – Saravanan

+0

Там нет других потоков? Кроме того, эта тема может представлять интерес: http://stackoverflow.com/questions/6683059/are-floating-point-numbers-consistent-in-c-can-they-be –

ответ

5

Если например ea.MinX: NaN, a будет NaN, и оба a > b и a < b будут false. Это означает, что есть объекты, которые сравниваются друг с другом.

Прежде всего вам нужно решить, как вы хотите, чтобы объекты, содержащие NaN, сортировались.

простой обходной путь может быть, чтобы вставить

if (double.IsNaN(a)) a = 0.0; 
if (double.IsNaN(b)) b = 0.0; 

Как отметил @Seph и @Jeppe в комментариях, double.CompareTo делает правильно, так что последняя строка может быть заменена return a.CompareTo(b);.

+0

+1 Это звучит правдоподобно - хотя я не уверен, почему результаты будут отличаться .Net-версиями. Но если там * может быть NaNs в данных (и OP говорит, что может), то это определенно вызовет вид проблемы, который был обнаружен. –

+0

Это имеет смысл, пожалуйста, позвольте мне временно удерживать эту нить и отмечать как ответ позже. Огромное спасибо. – Howard

+2

@MatthewWatson - возможно, функция 'Sort' в новой версии не делает ненужных сравнений и поэтому не может обнаружить несоответствия. – Henrik

0

Одна из возможных причин заключается в том, что ваша информация фактически изменяется во время сравнения.

Если вы выполните сортировку в фоновом потоке, вы обязательно получите эту ошибку, если сравнение будет получать разные значения для одного и того же элемента при запросе его дважды.

Если ваш основной поток обновляет одно из значений (возможно, путем привязки данных), в то время как сравнение выполняется, например.

Удостоверьтесь, что вы кэшируете сравниваемое значение, чтобы всегда получать согласованные результаты. Или согласитесь, что ошибка может произойти время от времени и повторить сортировку, если это произойдет.

Это также объяснит ваше чувство зависимости от машины/os. Проблемы многопоточности возникают по-разному в зависимости от различий программного и аппаратного обеспечения.

Смежные вопросы