检查数组是否是另一个数组的倍数

时间:2016-12-20 21:57:33

标签: python arrays numpy

我正在创建一个解决平面系统的程序,而且我一直在检测飞机是否重合。 AKA:我需要检查数组A的元素是否是数组B元素的倍数。 这就是我到目前为止所做的:


def coincident(one, two):
  div_ = one[0]/two[0]

  for v in zip(one[1:], two[1:]):
    if v[0]/v[1] != div_:
      return False
  return np.dot(one, two) != 0

它需要2个数组,目前不再是4个元素,并将第一个元素与它们分开。然后它遍历剩余的元素并检查被除数是否与' div _'相同。最后一行是考虑其中包含全零的数组,它使用numpy来点积,并检查它是否为零。

由于某些原因,它不能很好地工作,也不能很好地处理零(除以零)。

5 个答案:

答案 0 :(得分:5)

如果您确实需要完全倍数,那么:

Cygwin-PC ~/code_practice/Computing/stack
   $ gcc -DARRAY main.c stackImpl.c ../list/arrayImpl.o
/tmp/ccapgYQI.o:stackImpl.c:(.text+0x25): undefined reference to 
   `createList'
/tmp/ccapgYQI.o:stackImpl.c:(.text+0x4b): undefined reference to 

这是因为A⋅B= | A | * | B | * cos(t),其中t是两个向量之间的角度,所以(A⋅B)²= | A |²* | B |² *cos²(t)。如果向量是彼此的倍数,那么t是0或180度,并且cos²(t)== 1.

如果您正在使用浮点数,那么您应该允许一点舍入误差。例如,如果您希望向量的线性度在0.01度以内,并且您想要排除其中一个为0的情况,那么您可以这样做:

def coincident(one, two):
  return np.dot(one,two)*np.dot(one,two) == np.dot(one,one)*np.dot(two,two)

答案 1 :(得分:2)

创建一个二维数组,其列是输入数组(我假设它是一维的),并使用rank计算矩阵numpy.linalg.matrix_rank。如果输入数组重合,则等级将为1或更小。

以下是一些例子。首先,两个随机输入。一般来说,这些不一致,所以排名应该是2:

In [114]: np.random.seed(12345)

In [115]: x = np.random.rand(4)

In [116]: y = np.random.rand(4)

In [117]: np.linalg.matrix_rank(np.column_stack((x, y)))
Out[117]: 2

现在让y成为x的倍数:

In [118]: y = x/23

In [119]: np.linalg.matrix_rank(np.column_stack((x, y)))
Out[119]: 1

等级是1,正如预期的那样。

请注意,您的代码没有检测到这一点,因为它没有考虑正常的浮点不精确性:

In [120]: coincident(x, y)
Out[120]: False

答案 2 :(得分:1)

稍作修改,您可以按如下方式避免除零:

def coincident(one, two):
  div_ = one[0]/two[0] if two[0] else 1 

  for v in zip(one[1:], two[1:]):
    if v[0] != div_ * v[1]:
      return False
  return True

试验:

print(coincident([1.1,2.2,3.3],[2.2,4.4,6.6])) # True
print(coincident([0,0,0],[0,0,0])) # True
print(coincident([0,0,0],[0,1,0])) # False
print(coincident([1,-2,3],[2,4,6])) # False

答案 3 :(得分:0)

我认为这可以处理所有情况。

def coincident(l1, l2):
    try :
        d = l2[0] / l1[0]
    except ZeroDivisionError as e:
        d = 0
    if [x*d for x in l1] == l2:
        return True
    return False


l1 = [1,2,3]
l2 = [3,6,9]
print(coincident(l1, l2))

l1 = [0,6,9]
print(coincident(l1, l2))

输出:

True
False

答案 4 :(得分:0)

保持接近原始代码并考虑浮动pt数字,这是一种方法 -

def coincident(a, b):
    M = a/b.astype(float)
    return np.allclose(np.round(M),M) & np.allclose(np.diff(M),0)

我们的想法很简单,我们将第一个数组除以原始代码中的第二个数组,并通过将其与圆形数组版本进行比较来查看除法结果是或接近整数。

我们还检查所有元素的除法结果是否相同,并且区分这些结果并检查是否所有元素都接近0

样品运行 -

In [318]: b = np.random.rand(4)

In [319]: a = b*4.0

In [320]: coincident(a, b)
Out[320]: True

In [321]: a = b*4.5

In [322]: coincident(a, b)
Out[322]: False

In [323]: a = b*np.array([3,2,5,6])

In [325]: coincident(a, b)
Out[325]: False

In [326]: a = b*4.0

In [327]: coincident(a, b)
Out[327]: True

In [328]: a[1] = 100.0

In [329]: coincident(a, b)
Out[329]: False

如果您不关心被除数是否为整数,即多重性是否为整数,我们只考虑区分部分 -

def coincident_ignore_exact_divisibilty(a, b):
    return np.allclose(np.diff(a/b.astype(float)),0)