在Python中实现复数比较?

2024-10-01 13:41:10 发布

您现在位置:Python中文网/ 问答频道 /正文

我知道复数比较运算符一般不能定义。这就是python在尝试使用现成的复杂比较时抛出TypeError异常的原因。我明白为什么会这样(请不要偏离主题,试图解释为什么两个复数不能比较)。在

也就是说,在这个特殊的例子中,我想根据它们的大小来进行复数比较。换句话说,对于z1z2复值,则z1 > z2当且仅当abs(z1) > abs(z2),其中{}实现复数大小,如numpy.abs()。在

我想出了一个解决方案(至少我想我已经有了)如下:

import numpy as np

class CustomComplex(complex):
    def __lt__(self, other):
        return np.abs(self) < np.abs(other)
    def __le__(self, other):
        return np.abs(self) <= np.abs(other)
    def __eq__(self, other):
        return np.abs(self) == np.abs(other)
    def __ne__(self, other):
        return np.abs(self) != np.abs(other)
    def __gt__(self, other):
        return np.abs(self) > np.abs(other)
    def __ge__(self, other):
        return np.abs(self) >= np.abs(other)

complex = CustomComplex

这似乎有效,但我有几个问题:

  1. 是走这条路还是有更好的选择?在
  2. 我希望我的包透明地使用内置的complex数据类型以及numpy.complex。如何在没有代码重复的情况下优雅地完成这项工作?在

Tags: selfnumpyreturn定义defnp运算符abs
2条回答

我恐怕要偏离主题了(是的,我已经读了你的帖子了)。好吧,Python允许您尝试用这种方式比较复数,因为您可以单独定义所有运算符,即使我强烈建议您不要像您那样重新定义__eq__:您正在1 == -1!在

问题就在这里,并且会在某个时刻出现在你的面前(或者任何使用你的包的人的脸上):当使用等式和不等式时,普通人(和大多数python代码)会做一些简单的假设,比如-1 != 1(a <= b) && (b <= a)意味着{}。仅仅因为数学上的原因,这两个假设是不可能同时成立的。在

另一个经典假设是a <= b相当于-b <= -a。但是对于你来说,a <= b相当于-a <= -b!在

话虽如此,我将试着回答你的两个问题:

  • 1: 我觉得这是一种有害的方式(如上所述),但我没有更好的选择。。。在
  • 2: 我认为mixin可能是限制代码重复的一种优雅方式

但不是基于您自己的代码进行的广泛测试:

import numpy as np

class ComplexOrder(Object):
    def __lt__(self, other):
        return np.absolute(self) < np.absolute(other)
    # ... keep want you want (including or not eq and ne)
    def __ge__(self, other):
        return np.absolute(self) >= np.absolute(other)

class OrderedComplex(ComplexOrder, complex):
    def __init__(self, real, imag = 0):
        complex.__init__(self, real, imag)

class NPOrderedComplex64(ComplexOrder, np.complex64):
    def __init__(self, real = 0):
        np.complex64.__init__(self, real)

按照你的要求,我将放弃所有这可能是个坏主意的理由。在

Is this the way to go or is there a better alternative?

当普通的abs接受复数并且速度快得多的时候,不需要使用numpy。在functools中还有一个方便的total_ordering,它适用于这种简单的比较,如果您想减少代码(但这可能会比较慢):

from functools import total_ordering
@total_ordering
class CustomComplex(complex):
    def __eq__(self, other):
        return abs(self) == abs(other)
    def __lt__(self, other):
        return abs(self) < abs(other)

(这就是您需要的所有代码。)


I would like my package to transparently work with the built-in complex data type as well as numpy.complex. How can this be done elegantly, without code duplication?

当正确的参数是普通复数(或任意)数时,它会自动工作:

^{pr2}$

但是如果你想使用操作符<等等,而不是函数,那就是你能做的最好的了。complex类型不允许您设置__lt__,TypeError是硬编码的。在

如果要对普通complex数字进行这样的比较,则必须定义并使用自己的比较函数,而不是普通运算符。或者只使用abs(a) < abs(b),这是清楚的,不是非常冗长。在


*内置计时absnumpy.abs

>>> timeit.timeit('abs(7+6j)')
0.10257387161254883
>>> timeit.timeit('np.abs(7+6j)', 'import numpy as np')
1.6638610363006592

相关问题 更多 >