(Not 1) 由于某种原因评估为 -2
(Not 1) evaluates to -2 for some reason
为什么 (Not 1) 的计算结果为 -2?我希望它的计算结果为 0。
VBA/VBScript 没有真正的逻辑运算符(AND、OR、NOT)。您看到的逻辑运算符实际上是按位运算符,这就是您所得到的。 VBA 玩一些带有 True
和 False
值的游戏,所以这在大多数情况下都有效,但偶尔你会发现 "gotcha".
在这种情况下,您必须写 If InStr() <= 0 Then
,而不是 If Not InStr() Then
。
而不是 If InStr() Then
你必须写 If InStr() > 0 Then
换句话说:InStr()
returns一个数。不要试图将其视为布尔值。
1
不是True
的整数表示,-1
是。
Debug.Print CInt(True) 'prints -1
Debug.Print CInt(False) 'prints 0
布尔运算符(Not
、And
、Or
、XOr
)在其操作数为布尔值时的行为与 "logical operators" 相同。如果不是,它们的行为就像 "bitwise operators" 但事实是,它们总是 按位。
整数值1
转换为布尔值True
只是因为True
被定义为Not False
,这意味着any 非零值是一个布尔值 True
。但是,当您将 -1
用于 True
.
时,您只会得到 correct/expected 逻辑行为
一个Integer
用16位表示,所以1
是这样的:
0000 0000 0000 0001
这使得 Not 1
成为:
1111 1111 1111 1110
符号位打开,所以值为负 - trim 无意义的数字,你得到:
10
2
的二进制表示。因此,Not 1
是 -2
.
相反,-1
将是:
1111 1111 1111 1111
因此Not -1
是:
0000 0000 0000 0000
由于其他答案已经解释了原因,我想重点关注编码实践。
如您所见,Not x
不一定是您想要的。在实践中,你想要更像 Not CBool(x)
。但是,CBool()
可能会引发错误 - 例如,CBool(Null)
会产生错误 91(无效使用 null)。
可能声称您可以通过对变量进行强类型化来避免这种情况,但即使不使用 Variant
也不能保证在表达式中 Boolean
将保持 Boolean
.示例:
?typename(true and 0)
Integer
实际上,很容易不小心让 VBA 为您进行隐式转换,因此,出于这个原因,改变编码习惯可能更适合您。
为了测试真值,您需要像这样的表达式:
If x Then
对于虚假值,您需要像这样的表达式:
If x = False Then
无论 x
的类型如何,它们都有效,无论它是否是表达式,因此据说与 If x = True Then
或If Not x Then
。通过养成这种代码习惯,您可以帮助避免因意外从 Boolean
类型转换并获得按位运算而不是逻辑运算而产生的细微错误。
对于赋值,使用 Boolean
变量将确保它始终被强制转换为 True
或 False
而不是一些随机数。
为什么 (Not 1) 的计算结果为 -2?我希望它的计算结果为 0。
VBA/VBScript 没有真正的逻辑运算符(AND、OR、NOT)。您看到的逻辑运算符实际上是按位运算符,这就是您所得到的。 VBA 玩一些带有 True
和 False
值的游戏,所以这在大多数情况下都有效,但偶尔你会发现 "gotcha".
在这种情况下,您必须写 If InStr() <= 0 Then
,而不是 If Not InStr() Then
。
而不是 If InStr() Then
你必须写 If InStr() > 0 Then
换句话说:InStr()
returns一个数。不要试图将其视为布尔值。
1
不是True
的整数表示,-1
是。
Debug.Print CInt(True) 'prints -1
Debug.Print CInt(False) 'prints 0
布尔运算符(Not
、And
、Or
、XOr
)在其操作数为布尔值时的行为与 "logical operators" 相同。如果不是,它们的行为就像 "bitwise operators" 但事实是,它们总是 按位。
整数值1
转换为布尔值True
只是因为True
被定义为Not False
,这意味着any 非零值是一个布尔值 True
。但是,当您将 -1
用于 True
.
一个Integer
用16位表示,所以1
是这样的:
0000 0000 0000 0001
这使得 Not 1
成为:
1111 1111 1111 1110
符号位打开,所以值为负 - trim 无意义的数字,你得到:
10
2
的二进制表示。因此,Not 1
是 -2
.
相反,-1
将是:
1111 1111 1111 1111
因此Not -1
是:
0000 0000 0000 0000
由于其他答案已经解释了原因,我想重点关注编码实践。
如您所见,Not x
不一定是您想要的。在实践中,你想要更像 Not CBool(x)
。但是,CBool()
可能会引发错误 - 例如,CBool(Null)
会产生错误 91(无效使用 null)。
可能声称您可以通过对变量进行强类型化来避免这种情况,但即使不使用 Variant
也不能保证在表达式中 Boolean
将保持 Boolean
.示例:
?typename(true and 0)
Integer
实际上,很容易不小心让 VBA 为您进行隐式转换,因此,出于这个原因,改变编码习惯可能更适合您。
为了测试真值,您需要像这样的表达式:
If x Then
对于虚假值,您需要像这样的表达式:
If x = False Then
无论 x
的类型如何,它们都有效,无论它是否是表达式,因此据说与 If x = True Then
或If Not x Then
。通过养成这种代码习惯,您可以帮助避免因意外从 Boolean
类型转换并获得按位运算而不是逻辑运算而产生的细微错误。
对于赋值,使用 Boolean
变量将确保它始终被强制转换为 True
或 False
而不是一些随机数。