2016-06-08 101 views
3

为什么,在Python/numpy的:蟒蛇NumPy的奇怪的布尔运算的行为

from numpy import asarray 
bools=asarray([False,True]) 

print(bools) 
[False True] 

print(1*bools, 0+bools, 0-bools) # False, True are valued as 0, 1 
[0 1] [0 1] [ 0 -1] 

print(-2*bools, -bools*2)   # !? expected same result! :-/ 
[0 -2] [2 0] 

print(-bools)      # this is the reason! 
[True False] 

我认为这是奇怪的是-bools返回logical_not(bools),因为在所有其他情况下的行为是“算术”,而不是“逻辑” 。

一个谁想要使用布尔数组作为一个0/1面具(或“特色功能”)被强制使用某种方式渐开线表达式,如(0-bools)(-1)*bools,并且可以很容易招致成的bug,如果他忘了这个。

为什么会这样,而且这将是获得所期望的行为最好的可以接受的方式? (旁当然评论)

+1

我不明白为什么有人会使用一组布尔值作为掩码,而不是(0,1),这更直观,但我确实看到了一个观点。什么是期望的行为虽然做-2 *假? –

+0

+在Python中一切都是合乎逻辑的。如“blabla”为True(因此有点布尔)和一个字符串在同一时间。 –

+0

@ Ev.Kounis,当我想通过下面的代码写出一个延迟的指数衰减时,我偶然发现了它:delExpDecay = lambda t,d,a,tau:a * exp( - (t lurix66

回答

2

它的所有操作指令和数据类型。

>>> import numpy as np 
>>> B = np.array([0, 1], dtype=np.bool) 
>>> B 
array([False, True], dtype=bool) 

对于numpy,布尔数组被视为该布尔数组。应用于它们的每个操作都将首先尝试维护数据类型。也就是说方式:

>>> -B 
array([ True, False], dtype=bool) 

>>> ~B 
array([ True, False], dtype=bool) 

这是等价的,返回其元素的逐元素否定。但请注意,使用-B会引发警告,因为该功能已弃用。

当您使用了诸如:

>>> B + 1 
array([1, 2]) 

B1首先引擎盖相同的数据类型下铸造。在数据类型促销中,boolean阵列总是被铸造为numeric阵列。在上述情况下,B浇铸到int,因为其是相似的:

>>> B.astype(int) + 1 
array([1, 2]) 

在您的例子:

>>> -B * 2 
array([2, 0]) 

首先阵列B由操作者-否定,然后乘以2。期望的行为可以通过显式的数据变换被采用,或添加括号以确保正确操作顺序:

>>> -(B * 2) 
array([ 0, -2]) 

>>> -B.astype(int) * 2 
array([ 0, -2]) 

注意B.astype(int)可以没有数据拷贝由B.view(np.int8)取代,如布尔值由characters表示并且因此具有8位,因此可以将数据视为整数而不需要将其转换为.view方法。

>>> B.view(np.int8) 
array([0, 1], dtype=int8) 

因此,简而言之,B.view(np.int8)B.astype(yourtype)将始终ensurs即B[0,1]数字数组。

+0

谢谢您的全面解释,特别是关于代字符〜的说明。如果我们有一个波形符号运算符,为什么要使用一元减号“-'作为重复项?我更愿意认为它更符合逻辑,因为它们在像'0 + B'或'0-B'这样的操作中,一元加+和一元减'-'产生算术转换。 (另见我对上述自己的问题的评论) – lurix66

+0

@ lurix66这只是一个设计决定,显然他们对此表示遗憾,因为它被弃用,将来会被删除。当使用'-'作为二元运算符'0-B'或'B-0'时,它可以正常工作(如你所期望的),问题是当你使用'-'作为一元运算符'-B'时,被翻译为'-1 * B',如数值数组,它被翻译为'〜B'(或'not B')。同样,在numpy决定停止支持'-'一元运算符作为否定运算符之前,我们不能做任何事情,所以我们将不得不等待,或者同时更加小心:P –

0

numpy的阵列是同质-所有元素对于给定阵列相同的类型,并且该阵列对象存储那是什么类型。当您使用TrueFalse一个数组,它是bool类型的数组和经营者的行为阵列本身上。这并不奇怪,你会得到逻辑否定发生在对正常的bool逻辑否定的情况下。当您将数组用于整数运算时,它们将转换为1和0。在你所有的例子中,那些更为异常的情况,也就是说,它的行为不应该依赖于良好的代码。

正如评论所说,如果你想要做的数学0和1的阵列,它更好地只是让0和1组成的数组。然而,根据你想要对他们做什么,你可能会更好地服务于像numpy.where()这样的功能。

+0

(请参阅我对以前的问题的评论),如果简单,我认为其中一个内衬很有价值。对于我来说,使用'numpy.where()'看起来不那么简单,而不是使用布尔值掩码值为1的普通明显等价值,其中True和0为False。 – lurix66