为什么使用整数而不是长?

时间:2014-10-16 16:11:21

标签: integer long-integer integer-overflow vba

我经常会在看到与Overflow错误相关的问题。

我的问题是为什么使用integer变量声明而不只是将所有数值变量(double等除外)定义为long

除非您执行类似for循环的操作,否则您可以保证该值不会超过32,767的限制,是否会影响性能或其他不会使用long的内容?

8 个答案:

答案 0 :(得分:113)

  

整数变量存储为16位(2字节)数字

msdn

  

长(长整数)变量存储为带符号的32位(4字节)数字

msdn

因此,好处是减少了内存空间。一个整数占用了一半的内存。现在,我们讨论的是2个字节,所以除非你存储一个整数的TON,否则它不会产生真正的区别。

32 位系统上的

,16位整数会以无声方式静默转换为长整数可以使用更大范围的数字。溢出仍然发生,它需要同样多的内存。 Performance may even be hurt因为必须转换数据类型(在非常低的级别)。

不是我要找的参考,但....

  

我的理解是底层VB引擎将整数转换为long,即使它被声明为整数。因此,可以注意到轻微的速度降低。我已经相信了一段时间,也许这就是为什么上面的陈述,我没有要求推理。

ozgrid forums

这是我要找的参考资料。

  

简短回答,在32位系统中,2字节整数被转换为4字节   多头。实际上没有其他方法可以使各个位正确排列   任何形式的处理。请考虑以下

MsgBox Hex(-1) = Hex(65535) ' = True
     

显然-1不等于65535但计算机正在返回正确的值   回答,即   " FFFF" =" FFFF"

     

然而,如果我们强制将-1推向第一,我们就会得到正确的   回答(65535大于32k自动长)

MsgBox Hex(-1&) = Hex(65535) ' = False
     

" FFFFFFFF" =" FFFF"

     

一般来说,VBA没有必要声明" As Integer"在现代   系统,除了一些预期会收到的遗留API之外   整数。

pcreview forum

最后我发现msdn documentation我真的真的在寻找。

  

传统上,VBA程序员使用整数来保持小   数字,因为他们需要更少的内存。在最近的版本中,   但是,VBA会将所有整数值转换为Long类型,即使它们是“re”   声明为Integer类型。因此,不再具有性能优势   使用整数变量;实际上,Long变量可能略有不同   更快,因为VBA不必转换它们。

因此,总而言之,现在几乎没有理由使用Integer类型。 除非 ,否则需要使用期望16位int的旧API调用进行Interop。

  

有一点值得指出的是,一些旧的API函数可能期望16位(2字节)整数的参数,如果你是32位并试图传递整数(已经是4)通过引用它将无法工作,因为字节长度不同。

感谢Vba4All指出这一点。

答案 1 :(得分:11)

正如其他答案所述,int和long之间的真正区别在于其内存空间的大小,因此也就是它可以容纳的数字的大小。

这是有关这些数据类型的完整文档 http://msdn.microsoft.com/en-us/library/office/ms474284(v=office.14).aspx

整数是16位,可以表示介于-32,768和32,767之间的值

是32位,可以代表-2,147,483,648到2,147,483,647

并且有一个 LongLong ,这是64位,可以处理像9 pentilion

要记住的最重要的事情之一是数据类型因语言和操作系统/平台而异。在您的VBA世界中,长度为32位,但在64位处理器的c#中,长度为64位。这可能会引起很大的混淆。

虽然VBA不支持它,但当您转移到.net或java或其他语言中的任何其他语言时,我更喜欢使用 int16 int32 <的系统数据类型/ strong>和 int64 ,这使我对这些数据类型中可以保存的值更加透明。

答案 2 :(得分:7)

VBA有很多历史包袱。

一个Integer是16位宽,当16位架构/字大小普遍时,它是一个很好的默认数字类型。

Long为32位宽,应尽可能使用(IMO)。

答案 3 :(得分:6)

即使这篇文章已有四岁了,我对此还是很好奇,并进行了一些测试。需要注意的最重要的一点是,编码人员应 始终将变量声明为SOMETHING 。未声明的变量显然表现最差(技术上未声明为Variant

Long的执行速度最快,所以我认为Microsoft的建议始终使用Long而不是Integer是有意义的。我猜与Byte的情况相同,但是大多数编码人员都不使用它。

64位WINDOWS 10膝上型计算机的结果

Variable Olympics

使用的代码:

Sub VariableOlymics()
'Run this macro as many times as you'd like, with an activesheet ready for data
'in cells B2 to D6
Dim beginTIME As Double, trials As Long, i As Long, p As Long

    trials = 1000000000
    p = 0

    beginTIME = Now
    For i = 1 To trials
        Call boomBYTE
    Next i
    Call Finished(p, Now - beginTIME, CDbl(trials))
    p = p + 1

    beginTIME = Now
    For i = 1 To trials
        Call boomINTEGER
    Next i
    Call Finished(p, Now - beginTIME, CDbl(trials))
    p = p + 1


    beginTIME = Now
    For i = 1 To trials
        Call boomLONG
    Next i
    Call Finished(p, Now - beginTIME, CDbl(trials))
    p = p + 1


    beginTIME = Now
    For i = 1 To trials
        Call boomDOUBLE
    Next i
    Call Finished(p, Now - beginTIME, CDbl(trials))
    p = p + 1


    beginTIME = Now
    For i = 1 To trials
        Call boomUNDECLARED
    Next i
    Call Finished(p, Now - beginTIME, CDbl(trials))
    p = p + 1

End Sub


Private Sub boomBYTE()
Dim a As Byte, b As Byte, c As Byte

    a = 1
    b = 1 + a
    c = 1 + b
    c = c + 1

End Sub


Private Sub boomINTEGER()
Dim a As Integer, b As Integer, c As Integer

    a = 1
    b = 1 + a
    c = 1 + b
    c = c + 1

End Sub


Private Sub boomLONG()
Dim a As Long, b As Long, c As Long

    a = 1
    b = 1 + a
    c = 1 + b
    c = c + 1

End Sub


Private Sub boomDOUBLE()
Dim a As Double, b As Double, c As Double

    a = 1
    b = 1 + a
    c = 1 + b
    c = c + 1

End Sub


Private Sub boomUNDECLARED()

    a = 1
    b = 1 + a
    c = 1 + b
    c = c + 1

End Sub

Private Sub Finished(i As Long, timeUSED As Double, trials As Double)

    With Range("B2").Offset(i, 0)
            .Value = .Value + trials
            .Offset(0, 1).Value = .Offset(0, 1).Value + timeUSED
            .Offset(0, 2).FormulaR1C1 = "=ROUND(RC[-1]*3600*24,0)"
    End With

End Sub

答案 4 :(得分:4)

这是空间 vs 必要性问题。

在某些情况下使用长按必需。如果您循环遍历大型Excel文件中的行,则保存行号的变量应该很长。

但是,有时你会知道一个整数可以处理你的问题而使用一个长整数会浪费空间(内存)。个别变量确实没有多大区别,但是当你开始处理数组时,它可以产生很大的不同。

  • 在VBA7中,整数是2个字节,长整数是4个字节

  • 如果您有一个介于1和10之间的100万个数字的数组,则使用整数数组将占用 2MB的RAM,而长数组的RAM大约为4MB。

答案 5 :(得分:1)

我采用了@PGSystemTester的方法并对其进行了更新,以消除一些潜在的可变性。通过将循环放入例程中,可以减少调用例程所花费的时间(这是很多时间)。我还关闭了屏幕更新功能,以消除可能引起的任何延迟。

Long仍然表现最好,并且由于这些结果仅局限于变量类型的影响,因此变化幅度值得关注。

我的结果(台式机,Windows 7,Excel 2010):

enter image description here

使用的代码:

Option Explicit

Sub VariableOlympics()
'Run this macro as many times as you'd like, with an activesheet ready for data
'in cells B2 to D6
Dim beginTIME As Double, trials As Long, i As Long, p As Long
Dim chosenWorksheet As Worksheet

    Set chosenWorksheet = ThisWorkbook.Sheets("TimeTrialInfo")

    Application.EnableEvents = False
    Application.Calculation = xlCalculationManual
    Application.ScreenUpdating = False

    trials = 1000000000 ' 1,000,000,000 - not 10,000,000,000 as used by @PGSystemTester

    p = 0

    beginTIME = Now
    boomBYTE trials
    Finished p, Now - beginTIME, CDbl(trials), chosenWorksheet.Range("B2")
    p = p + 1

    beginTIME = Now
    boomINTEGER trials
    Finished p, Now - beginTIME, CDbl(trials), chosenWorksheet.Range("B2")
    p = p + 1


    beginTIME = Now
    boomLONG trials
    Finished p, Now - beginTIME, CDbl(trials), chosenWorksheet.Range("B2")
    p = p + 1


    beginTIME = Now
    boomDOUBLE trials
    Finished p, Now - beginTIME, CDbl(trials), chosenWorksheet.Range("B2")
    p = p + 1


    beginTIME = Now
    boomUNDECLARED trials
    Finished p, Now - beginTIME, CDbl(trials), chosenWorksheet.Range("B2")
    p = p + 1

    Application.EnableEvents = True
    Application.Calculation = xlCalculationAutomatic
    Application.ScreenUpdating = True
    chosenWorksheet.Calculate

End Sub


Private Sub boomBYTE(numTrials As Long)
Dim a As Byte, b As Byte, c As Byte

Dim i As Long
For i = 1 To numTrials
    a = 1
    b = 1 + a
    c = 1 + b
    c = c + 1
Next i

End Sub


Private Sub boomINTEGER(numTrials As Long)
Dim a As Integer, b As Integer, c As Integer

Dim i As Long
For i = 1 To numTrials
    a = 1
    b = 1 + a
    c = 1 + b
    c = c + 1
Next i

End Sub


Private Sub boomLONG(numTrials As Long)
Dim a As Long, b As Long, c As Long

Dim i As Long
For i = 1 To numTrials
    a = 1
    b = 1 + a
    c = 1 + b
    c = c + 1
Next i

End Sub


Private Sub boomDOUBLE(numTrials As Long)
Dim a As Double, b As Double, c As Double

Dim i As Long
For i = 1 To numTrials
    a = 1
    b = 1 + a
    c = 1 + b
    c = c + 1
Next i

End Sub


Private Sub boomUNDECLARED(numTrials As Long)
Dim a As Variant, b As Variant, c As Variant

Dim i As Long
For i = 1 To numTrials
    a = 1
    b = 1 + a
    c = 1 + b
    c = c + 1
Next i

End Sub

Private Sub Finished(i As Long, timeUSED As Double, trials As Double, initialCell As Range)

    With initialCell.Offset(i, 0)
            .Value = trials
            .Offset(0, 1).Value = timeUSED
            .Offset(0, 2).FormulaR1C1 = "=ROUND(RC[-1]*3600*24,2)"
    End With

End Sub

答案 6 :(得分:0)

正如其他人已经提到的, 占用的空间可能是 Integer 的两倍。正如其他人已经提到的那样,除非您要处理额外的超大量数据,否则,当前计算机的高容量意味着您将不会看到任何性能上的差异

内存

考虑到 1百万个值,对于每个值,使用整数和长整型之间的差为2个字节,因此2 * 1 000 000 / 1,024 / 1024 = 小于2您的RAM中的差异为MB ,这可能远远小于RAM容量的1%甚至0.1%。

处理

考虑到PGSystemTester所做的基准测试,当处理100亿个批处理(共4个操作)时,Long和Integer之间相差811-745 = 66秒。将数量减少到 100万次操作,我们可以预期66/10000/4 = 执行时间差异小于2ms。


我个人使用Integers和Longs来帮助提高代码的可读性,尤其是在循环中,其中Integer表示循环应该很小(小于1000次迭代),而Long告诉我该循环预计会很大(超过1000个)。

请注意,此主观阈值远低于整数上限,我使用Longs只是为了区分自己的大小定义。

答案 7 :(得分:-7)

也许CS毕业可以更好地解释它,但是整数需要更少的内存来存储(可能与非常简单的VBA脚本无关)。

它还保证/验证变量将始终为整数(非小数)。我很确定如果你将6.7存储为整数,它将在VBA中转换为数字7。

执行此操作可能不是最佳做法,但可能存在需要这样做的情况。我认为主要目的是数据验证/完整性。特别是,对于需要发生某些事情的循环是的,X次 - 小数没有意义。

主要区别在于内存 - 如果我记得长是64位而整数是32位。