为什么 (Not 1) 评估为 -2?我希望它评估为 0。
3 回答
1
不是 的整数表示True
,-1
是。
Debug.Print CInt(True) 'prints -1
Debug.Print CInt(False) 'prints 0
当操作数是布尔值时,布尔运算符 ( Not
, And
, Or
, XOr
) 表现为“逻辑运算符”。当它们不是时,它们表现为“按位运算符”,但事实是,它们总是按位的。
整数值1
转换为布尔值True
只是因为True
定义为Not False
,这意味着任何非零值都是布尔值True
。但是,当您使用-1
for时,您只会得到正确/预期的逻辑行为True
。
AnInteger
由 16 位表示,因此1
是这样的:
0000 0000 0000 0001
这使得Not 1
:
1111 1111 1111 1110
符号位打开,因此值为负 - 修剪无关紧要的数字,您会得到:
10
这是 的二进制表示2
。因此,Not 1
是-2
。
相反,-1
将是:
1111 1111 1111 1111
因此Not -1
:
0000 0000 0000 0000
VBA/VBScript 没有真正的逻辑运算符(AND、OR、NOT)。您看到的逻辑运算符实际上是按位运算符,这就是您所得到的。True
VBA 使用和值玩一些游戏,False
所以这在大多数情况下都有效,但偶尔你会发现一个“陷阱”。
在这种情况下,If Not InStr() Then
您不必编写If InStr() <= 0 Then
.
而不是If InStr() Then
你必须写If InStr() > 0 Then
换句话说:InStr()
返回一个数字。不要试图将其视为布尔值。
正如其他答案已经解释了为什么,我想专注于编码实践。
正如你所发现的,Not x
不一定是你想要的。在实践中你想要更多像Not CBool(x)
. 但是,CBool()
可能会引发错误 - 例如,CBool(Null)
产生错误 91(无效使用 null)。
可能有人声称您可以通过对变量进行强类型化来避免这种情况,但即使不使用 aVariant
也不能保证在表达式中 aBoolean
将保持 a Boolean
。例子:
?typename(true and 0)
Integer
在实践中,很容易意外地让 VBA 为您执行 voodoo 隐式转换,因此,出于这个原因,改变编码习惯可能更适合您。
为了测试真实值,您需要如下表达式:
If x Then
对于虚假值,您需要如下表达式:
If x = False Then
无论 的类型如何,无论是否是表达式,这些作品都有效,x
因此据说与If x = True Then
or相比,其行为更加一致/可预测If Not x Then
。通过采用这种代码习惯,您可以帮助避免因意外转换Boolean
类型和获得按位运算而不是逻辑运算而产生的细微错误。
对于分配,使用Boolean
变量将有助于确保它始终被强制转换为随机数True
或非False
随机数。