VBA 中涉及两个整数和一个长整数的溢出错误

Posted

技术标签:

【中文标题】VBA 中涉及两个整数和一个长整数的溢出错误【英文标题】:Overflow error in VBA involving two integers and a Long Integer 【发布时间】:2017-10-30 21:03:28 【问题描述】:

我不会在 VBA 中编写代码,但我需要调试其中编写的代码。当我运行代码时,我收到了一个溢出错误,我在网上查看了该错误。我在调试器中使用断点来查找导致错误的代码行。

这是行:

lngInt = nIntA * nIntB

调试器说 nIntA(一个整数)= 4,851,nIntB(另一个整数)= 10。lngInt 是一个长整数,如果我没看错的话:

dim lngInt As Long

nIntA 和 nIntB 初始化为:

Public nIntA As Integer 
Public nIntB As Integer

如果有帮助,两者都是从 Access 表单中设置的。

这似乎没有给我一个问题,所以我假设这是 VBA 中的一个怪癖。什么可能导致错误?

提前谢谢你!

【问题讨论】:

Integer * Integer 给出Integer,所以4851 * 10 在隐式转换为Long 以存储在lngInt 之前给出Overflow。使用lngInt = CLng(nIntA) * CLng(nIntB) 或者简单地改变声明Public nIntA As LongPublic nIntB As Long 无论如何,您的 16 位 Integer 变量在内部是在 32 位上计算的,就像 Long 整数一样,那么为什么不声明它们 As Long 呢?这不是“VBA 怪癖”,而是表达式赋值的工作原理:表达式需要在其结果被赋值之前被评估,Integer * Integer 将是Integer。不要责怪这门语言,VBA 的“怪癖”比人们想象的要少得多——无论如何,它比 javascript 数学要少得多。 【参考方案1】:

Integer 类型已过时。您可以随心所欲地声明和使用 16 位整数,VBA 运行时将强制执行其限制,但在内部它无论如何都(默默地)转换为 32 位整数,所以为什么不直接使用 Long(32 位) 首先是整数?

也就是说,这与“VBA 怪癖”无关,而是与基础有关:

foo = [expression]

在运行时可以执行foo 的分配之前,需要评估[expression]。 “怪癖”是 VBA 不关心 foo 的类型,直到 之后 [expression] 被评估,因为无论如何它都必须(隐式)将其转换为该类型:

Dim foo As Double
foo = 2 + 2

2 + 2 是否应该自行评估为Double?它没有,也不需要。 2 + 2 的计算结果为 4,由于两个操作数都是 Integer,因此结果将是 Integer,因此赋值为:

Dim foo As Double
foo = CDbl((2 + 2))

现在,如果您有两个 Integer 值相乘,并且总数溢出类型,根据规范,您会得到 overflow 错误。

Dim foo As Long
foo = 32000 * 2

因为那仍然是:

Dim foo As Long
foo = CLng((32000 * 2))

注意内括号:(32000 * 2) 被评估为 Integer之前结果可以转换为 Long,并且该转换的结果分配给 foo。 p>

如果其中一个操作数是 Long,则结果将是 Long - 因为两个操作数都是 Integer,所以结果将是 Integer


如果您想要时髦的表达式和令人难以置信的隐式转换,请尝试使用 Javascript。 VBA 在这里一点也不“古怪”。

【讨论】:

@YowE3K MSDN states it rather plainly - 另见this answer 关于这个主题。 所以你的意思是我应该将两个 IntA 和 IntB 声明为 Long 整数,这样它们的乘积就不会导致溢出? @JoubertLucas 表达式将计算为其操作数使用的最宽类型,因此两者之一需要是 long 才能使表达式计算为 long,是的。

以上是关于VBA 中涉及两个整数和一个长整数的溢出错误的主要内容,如果未能解决你的问题,请参考以下文章

VBA 溢出行为

[位运算] 64位整数乘法(mod 一个数)

为啥使用整数而不是长整数?

4.数据类型分类:

在 VBA 中睡觉(整数溢出!!)

RandomizedSearchCV 溢出错误:无法将“int”放入索引大小的整数中