VBA:变体数据类型的意外行为

时间:2016-09-12 19:09:25

标签: vba

根据MSDN,对于Variant数据类型:

  

“数值数据可以是-1.797693134862315E308到-4.94066E-324为负值的任何整数或实数值,从正值为4.94066E-324到1.797693134862315E308。”

但是,即使计算后的所有最终值都落在可接受的范围内,以下代码也会出错:

Sub Test()

Dim v1, v2, v3, v4

v1 = 569847501 + 54678                  '  OKAY
v2 = 7784687414# + 98565821345#         '  OKAY
v3 = 7784687414# + 1132747441           '  OKAY
v4 = 1132747441 + 1788441323            '  FAILS

End Sub

MSDN也指出:

  

“但是,如果对包含Byte,Integer,Long或Single的Variant执行算术运算,并且结果超出原始数据类型的正常范围,则结果将在Variant中提升为下一个更大的数据类型。 Byte被提升为Integer,Integer被提升为Long,Long和Single被提升为Double。“

文档说明当算术运算超出原始数据类型的正常范围时,应该提升类型。为什么v4未升级为Double

2 个答案:

答案 0 :(得分:6)

来自https://support.microsoft.com/en-us/kb/199809 - 参见粗体声明

  

此语句生成溢出错误,因为24 * 24 * 60 =   34560,超过了2字节整数的最大大小(32767)。    Visual Basic不会评估整个表达式以检查   结果的大小 ,而是继续使用2字节的临时值   计算空间。如果您发生相同的溢出错误   将前面的值声明为常量并将常量相乘。

     

为了解决这种问题,总是很重要   在数值计算中使用它们时显式键入数字   在定义常量时。如果前面的表达式更改为   以下内容:

所以改成它......

v4 = 1132747441# + 1788441323#

......诀窍,但肯定闻到了。

答案 1 :(得分:6)

您正在使用不是变体的数字文字。它们被编译器解释为容纳文字值的最小必要类型,尽管Byte值将默认为Integer类型。

Debug.Print TypeName(1132747441) 'Long
Debug.Print TypeName(1788441323) 'Long

正如@ComIntern指出的那样,你在表达式中分配2个long的结果,表达式在分配给Variant v4

之前溢出

正如@dazedandconfused指出的那样,您可以将文字值强制转换为更合适的类型,并且表达式将进行评估,并且可以分配变体。

为了获得Microsoft为Variant类型记录的行为,您需要将文字值强制转换为 之前在表达式中使用它们。两个变体都将包含 Long,但您将获得文档声明的自动重新输入。

Sub Test()

  Dim v1, v2, v3, v4

  Debug.Print TypeName(1132747441) 'Long
  Debug.Print TypeName(1788441323) 'Long

  Dim v5, v6

  v5 = 1132747441
  v6 = 1788441323

  Debug.Print TypeName(v5) 'Long
  Debug.Print TypeName(v6) 'Long

  v4 = v5 + v6 'OKAY
  Debug.Print TypeName(v4) 'Double

  v4 = 0
  Debug.Print TypeName(v4) 'Integer

  v4 = CVar(1132747441) + CVar(1788441323) ' OKAY
  Debug.Print TypeName(v4) 'Double


  v1 = 569847501 + 54678                  '  OKAY
  v2 = 7784687414# + 98565821345#         '  OKAY
  v3 = 7784687414# + 1132747441           '  OKAY
  v4 = 1132747441 + 1788441323            '  FAILS

End Sub