(Не 1) оценивается как -2 по какой-то причине - PullRequest
3 голосов
/ 07 марта 2019

Почему (не 1) оценивается как -2?Я ожидал бы, что это оценит как 0.

enter image description here

Ответы [ 3 ]

5 голосов
/ 07 марта 2019

1 не является целочисленным представлением True, -1 is.

Debug.Print CInt(True) 'prints -1
Debug.Print CInt(False) 'prints 0

Булевы операторы (Not, And, Or, XOr) ведут себякак «логические операторы», когда их операнды являются логическими значениями.Когда это не так, они ведут себя как «побитовые операторы», но на самом деле они всегда побитовые.

Целочисленное значение 1 преобразуется в логическое значение Trueтолько потому, что True определено как Not False, что означает любое ненулевое значение, является логическим True.Но вы получите правильное / ожидаемое логическое поведение, только если вы используете -1 для True.

. Integer представляется 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
3 голосов
/ 07 марта 2019

VBA / VBScript не имеет реальных логических операторов (И, ИЛИ, НЕ).Логические операторы, которые вы видите, на самом деле являются побитовыми, и это все, что вы получаете.VBA играет в некоторые игры со значениями True и False, так что это работает большую часть времени, но иногда вы можете найти «поймал».

В этом случае вместо If Not InStr() Then у вас естьдля записи If InStr() <= 0 Then.
Вместо If InStr() Then необходимо написать If InStr() > 0 Then

Другими словами: InStr() возвращает число .Не пытайтесь рассматривать это как логическое значение.

2 голосов
/ 07 марта 2019

Поскольку другие ответы уже объясняли, почему почему , я хочу сосредоточиться на практике кодирования.

Как вы узнали, 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, а не к некоторым случайным числам.

...