为什么会这样,在 python/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)
很奇怪,因为在所有其他情况下,行为是“算术的”,而不是“逻辑的”。
想要使用 boolean 数组作为 0/1 掩码(或“特征函数”)的人被迫使用某种渐开线表达式,例如 (0-bools)
或 (-1)*bools
,如果他忘记了这一点,很容易导致错误。
为什么会这样,获得所需行为的最佳可接受方式是什么? (当然除了评论)
最佳答案
一切都与运算符顺序和数据类型有关。
>>> import numpy as np
>>> B = np.array([0, 1], dtype=np.bool)
>>> B
array([False, True], dtype=bool)
对于 numpy, boolean 数组被视为 boolean 数组。对它们应用的每一个操作,都会首先尝试维护数据类型。就是这样:
>>> -B
array([ True, False], dtype=bool)
和
>>> ~B
array([ True, False], dtype=bool)
它们是等价的,返回其元素的逐元素否定。但是请注意,使用 -B
会引发警告,因为该函数已被弃用。
当你使用像这样的东西时:
>>> B + 1
array([1, 2])
B
和 1
首先在幕后转换为相同的数据类型。在数据类型提升中,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)
,因为 boolean 值由 表示字符
,因此有 8 位,数据可以通过 .view
方法查看为整数,无需转换。
>>> B.view(np.int8)
array([0, 1], dtype=int8)
所以,简而言之,B.view(np.int8)
或 B.astype(yourtype)
将始终确保 B
是[0,1]
数值数组。
关于python numpy 奇怪的 boolean 算术行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37697280/