3

为什么 (Not 1) 评估为 -2?我希望它评估为 0。

在此处输入图像描述

4

3 回答 3

5

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。但是,当您使用-1for时,您只会得到正确/预期的逻辑行为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
于 2019-03-07T17:40:58.057 回答
3

VBA/VBScript 没有真正的逻辑运算符(AND、OR、NOT)。您看到的逻辑运算符实际上是按位运算符,这就是您所得到的。TrueVBA 使用和值玩一些游戏,False所以这在大多数情况下都有效,但偶尔你会发现一个“陷阱”。

在这种情况下,If Not InStr() Then您不必编写If InStr() <= 0 Then.
而不是If InStr() Then你必须写If InStr() > 0 Then

换句话说:InStr()返回一个数字。不要试图将其视为布尔值。

于 2019-03-07T17:40:25.290 回答
2

正如其他答案已经解释了为什么,我想专注于编码实践。

正如你所发现的,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 Thenor相比,其行为更加一致/可预测If Not x Then。通过采用这种代码习惯,您可以帮助避免因意外转换Boolean类型和获得按位运算而不是逻辑运算而产生的细微错误。

对于分配,使用Boolean变量将有助于确保它始终被强制转换为随机数True或非False随机数。

于 2019-03-07T18:01:49.763 回答