VBA关于双边不平等的政策?

时间:2017-05-02 20:24:25

标签: vba

试图减少代码的长度,以至于减少了查看和调试的麻烦,我一直在愚弄,我偶然发现了这个奇怪的事实:

Debug.Print 5<9<8 'returns "True"

起初我以为这是因为它只检查了第一组,但后来我找到了

Debug.Print 5<4<8 '*also* returns "True"

VBA是否将这种三重不等式解释为Or语句?我无法想象为什么有人会选择做出VBA所做的解释,因为它几乎肯定是较少使用的选项,但我很难想到另一种解释。

此外,编写If 5 < X < 8 Then(使用样本编号)的快速而漂亮的方法是什么,而不必诉诸无尽的And语句,即If 5 < x And X < 8 Then?一个语句没问题,但长度加倍会加快,特别是因为变量通常不是X

编辑:好吧,它当然不是Or,因为VBA还说Debug.Print 8<6<2True。究竟是什么思考?

5 个答案:

答案 0 :(得分:4)

我没有任何线索,但我的教育猜测是,它首先评估等式左边(5 <9),得到真。然后,它继续评估其余部分(TRUE&lt; 8)并隐式地将TRUE转换为其整数值(我相信这在VB中为-1)。

-1&lt; 8 - &gt; TRUE

同样适用于第二种情况,因为FALSE将转换为0和0 <8。

基本上它与将布尔值隐式转换为整数以及它们在VBA中的相应值有关。

答案 1 :(得分:3)

它与VBA评估表达式和隐式转换的方式有关。计算等式的第一部分,并将结果存储为数值(布尔值隐式转换为整数)

(嗯......从技术上讲,布尔 只是一个整数,但我们只是这样......)

'// True = -1
'// False = 0

Debug.Print 5 < 9 < 8

Debug.Print CInt(5 < 9) '// Prints -1

Debug.Print -1 < 8 '// = True

这就是为什么以下给出&#34; False&#34;代替:

Debug.Print 5 < 9 < -1

由于

Debug.Print Cint(5 < 9) '// True = -1
Debug.Print -1 < -1 '// False

如果你想知道某些东西是否在另外两个数字的中间,那么你必须使用And运算符来强制进行单独的评估(然后评估运算符的任一侧并进行逻辑比较)< / p>

Debug.Print (3 < 5 And 5 < 4) '// False

答案 2 :(得分:3)

从解析树的角度来看,它可以为为什么以这种方式工作提供更多的启示。

排除THEN令牌之后的任何指令,If 5 < X < 8 Then的解析树可能看起来像这样(非常简化):

expression tree

比较运算符是二元运算符,其两侧都有表达式,并且为了解析{{}的布尔表达式1}},VBA需要按特定的顺序访问树节点:因为VBA从左到右解析表达式,IfBlockStatement部分独立地作为表达式,然后该表达式的结果用于解析表达式的5 < X部分。

因此,当VBA解析{expression} < 8时,因为它是5 < X,结果是ComparisonExpression值;当需要将该布尔值与Boolean整数文字进行比较时,VBA会执行隐式类型转换并实际比较8,无论第一个结果是什么,它都将评估为CInt({Boolean}) < 8表达式,因为True转换为False0在表示为整数字面时转换为True,并且都是-1

这些机制内置于运行时的工作方式,因此为了评估< 8X之间是否5,您需要构建表达式,以便它能够在8If X > 5 And X < 8 Then 之间运行。解析如下:

LogicalAndOperator

它为您提供了两个不同的表达式树,它们由{{1}}连接,然后在两边都有效的布尔表达式。

答案 3 :(得分:0)

5&lt; 9&lt; 8 = True&lt; 8 = True

5&lt; 4&lt; 8 = False&lt; 8 = True

答案 4 :(得分:0)

其他答案很好地掩盖了问题的第一部分,但未令人满意地掩盖了问题的第二部分,即 If 5 < X < 8 Then的一种快速而美观的书写方式是什么(使用样本编号),而不必诉诸于无尽的And语句,即If 5 < x And X < 8 Then

有两种方法。第一个:

Select Case X
    Case 5 To 8
    ...
End Select

在此,关键字To之前的值必须是两者中较小的值。还要注意,尽管这将适用于整数,但我不知道它是否适用于Double之类的类型(我怀疑不会)。

第二种方法,不管区间边界是否为整数,都可以工作,但不一定会更短,但是它可以通过一次比较来评估事物:

If Sgn(x - 5) + Sgn(x - 8) = 0 Then ...

这是一种评估值是否在某些范围之间的有趣方法,因为它还可以提供有关该值是否等于这些范围之一或“超出”范围(以及位于哪个“范围”)的信息。 )。例如,在-∞..0..+∞轴上:

  • 如果x = 4,则上面的表达式为-2,因此x位于(5..8)区间的左侧
  • 如果x = 5,则上面的表达式为-1,因此x是(5..8)区间的左边界
  • 如果x = 6,则上面的表达式为‘0,因此x在(5..8)区间之内,即在其边界之间。
  • 如果x = 8,则上面的表达式为1,因此x是(5..8)区间的右边界
  • 如果x = 9,则上面的表达式为2,因此x位于(5..8)区间的右侧

当然,如果要在区间中包括边界,例如测试If 5 <= x And X <= 8 Then,则上面的比较将变为If Abs(Sgn(x - 5) + Sgn(x - 8)) < 2 Then ...,这是检查表达式是否为-1,0的另一种快捷方式或1。

最后,以上方法都不比Between(x, 5, 8)假设函数短,但至少它们是“经典”方法的替代方法。