2015-07-15 4 views
2

Я пытаюсь проверить два нормальных вектора для равенства. Мой нормальный вектор представлен как список из трех элементов, один элемент для каждой пространственной координаты (X, Y и Z). Все координаты округлены до 4 знаков после запятой. Я хочу, чтобы проверить, если две поверхности имеют одинаковое нормальное, так что у меня есть что-то вроде следующего:Как переопределить сравнение для float в списке в Python?

if (surface1.normal in [surface2.normal, self.NegatedNormal(surface2.normal)]): 
    # do stuff here 

Проблема заключается в мои нормалей выглядеть следующим образом:

surface1.normal: [0.9947, 0.0155, 0.1015] 
surface2.normal: [0.9947, 0.0155, 0.1014] 

Обратите внимание, что г-координата выкл. на 0.0001. Итак, есть ли способ переопределить оператор equals для принятия ответов в пределах 0.0001 друг от друга, который совместим со сравнением в других структурах данных (например, в моем случае)? У меня такое чувство, что мне придется написать свой собственный метод __eq__, но я не совсем уверен, как это сделать.

Также, если это не лучший способ действий, является ли их лучшим способом сравнить два списка поплавков в пределах данного допуска?

+1

Вы можете написать пользовательский объект с плавающей точкой, который наследуется от обычного поплавка, но написать свои собственные функции для своих операторов (например, '__ge __() является> =') – SuperBiasedMan

+0

@SuperBiasedMan Это является интересным подходом. К сожалению, это потребует рефакторинга большого количества кода, поэтому я не решаюсь его попробовать, но я не знал, что вы можете наследовать от примитивных типов, так что хорошо помнить о будущем. – samalamma708

+0

Да, вы можете по существу сделать подкласс примитива, а затем переписать только те функции, которые вы хотите вести по-разному. – SuperBiasedMan

ответ

3

Вы можете написать пользовательскую функцию для этого. Например:

def comp_floats(x, y, delta): 
    return abs(x - y) < delta 

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

+0

Я знаю, что могу это сделать, но я ищу что-то более универсальное, которое будет работать с другой логикой программирования. Например, логическое значение в исходном столбце возвращает true для определенного допуска или surface1.normal == surface2.normal возвращает true. В основном я ищу хороший способ перегрузить операторы сравнения, но я не уверен, как это сделать на Python, или если это возможно даже с учетом эффекта, который я собираюсь сделать. – samalamma708

+0

Вы не можете переопределить ключевые слова/символы в Python. Так вы можете это сделать. –

+0

Я бы сказал, что правильным способом сравнения 2 поплавков было бы: 'abs (x - y)

2

Вы не можете изменять свойства встроенного списка, но вы можете переопределить их, перейдя на свой собственный подкласс класса.

class CustomList(list): 
    deviation = None 

    def deviation_check(self, val1, val2): 
     if self.deviation: 
      return min(val1, val2) + self.deviation >= max(val1, val2) 
     return val1 == val2 

    def __eq__(self, other): 
     is_equal = (self.deviation_check(self[0], other[0]) and 
        self.deviation_check(self[1], other[1]) and 
        self.deviation_check(self[2], other[2])) 

     return is_equal 

l = CustomList() 
l.deviation = 0.0001 # Note: Added deviation as a property 
l.extend([0.9947, 0.0155, 0.1015]) 

l1 = CustomList() 
l1.extend([0.9947, 0.0155, 0.1014]) 

print l == l1 

Теперь мы два CustomList объекты л и l1, когда-либо вы пытаетесь проверить равенство между списками l == l1, питон проверить это равенство таким образом l.__eq__(l1), так что по этой причине мы перекрываться __eq__ магии метод для работы по своему усмотрению.

Если вы не добавили l.deviation, он проверяет равенство. также вам нужно четко указать, с какой стороны вы должны добавить значение deviation.

Как я уже сказал l == l1 преобразуется в l.__eq__(l1) в питоне, поэтому вы, чтобы добавить deviation свойства список объекта, который находится в левой стороне ==.

Если запустить данный скрипт ..

# Output --------------- 
True 

Это потому, что мы определили l.deviation == 0.0001, это делает разницу в проверке равенства.

Надеется, что это решает проблему ..

+0

определение функции __eq __ (я, другое): если Len (Я) = Len (другие): вернуть Ложные возвращение всех ([self.deviation_check (пункт, другой [индекс]) для индекса, пункт в enumerate (self)]) 'Это будет работать для любого списка длин, а не только 3 длины, с которой работает ваш выше ответ. –

+0

@ gsb-eng Вы должны переопределить конструкцию списка, чтобы добавить там параметр отклонения. Что-то вроде '__init __ (self, * args, deviation = 1e-3)' с подходящим 'супер (CustomList, self) .__ init __ (* args)' должен работать, чтобы вы могли создавать 'CustomList (1,2,3,4 , 5, отклонение = 1e-6) '(не проверено, поэтому оно может иметь опечатки). –