Programing

Long 대신 Integer를 사용하는 이유는 무엇입니까?

lottogame 2020. 12. 7. 07:40
반응형

Long 대신 Integer를 사용하는 이유는 무엇입니까?


Overflow 오류와 관련된 질문을 자주 봅니다 .

내 질문은 integer모든 숫자 변수 ( double제외 )를 정의하는 대신 변수 선언을 사용하는 이유입니다 long.

값이 32,767 제한을 초과하지 않는다는 것을 보장 할 수있는 for 루프와 같은 작업을 수행하지 않는 한 성능에 영향을 미치거나 사용하지 않음을 지시하는 다른 무언가가 long있습니까?


정수 변수는 16 비트 (2 바이트) 숫자로 저장됩니다.

msdn

Long (long 정수) 변수는 부호있는 32 비트 (4 바이트) 숫자로 저장됩니다.

msdn

따라서 이점은 메모리 공간 감소입니다. Integer는 long이 수행하는 메모리의 절반을 차지합니다. 자, 우리는 2 바이트에 대해 이야기하고 있으므로 TON의 정수를 저장하지 않는 한 실제 차이를 만들지 않을 것입니다.

하지만 A의 32 비트 시스템, 16 비트 정수는 자동으로 작업의 숫자의 더 큰 범위의 혜택없이 오래로 변환됩니다. 오버플로는 여전히 발생하며 많은 메모리가 필요합니다. 성능도 할 수있다 상처 데이터 유형이있다 (매우 낮은 수준)로 변환 할 수 있기 때문이다.

내가 찾던 레퍼런스는 아니지만 ....

내 이해는 기본 VB 엔진이 정수로 선언 된 경우에도 정수를 long으로 변환한다는 것입니다. 따라서 약간의 속도 감소를 확인할 수 있습니다. 나는 이것을 한동안 믿어 왔고 아마도 그것이 위의 진술이 만들어진 이유 일 것입니다. 나는 추론을 요구하지 않았습니다.

ozgrid 포럼

이것이 제가 찾고 있던 참고 자료입니다.

간단히 대답하면 32 비트 시스템에서 2 바이트 정수는 4 바이트 Long으로 변환됩니다. 모든 형태의 처리에 대해 각 비트가 올바르게 정렬되도록하는 다른 방법은 없습니다. 다음을 고려하세요

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

분명히 -1은 65535와 같지 않지만 컴퓨터는 "FFFF"= "FFFF"라는 정답을 반환합니다.

그러나 -1을 먼저 길게 강요했다면 올바른 답을 얻었을 것입니다 (65535가 32k보다 크면 자동으로 길어집니다).

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

"FFFFFFFF"= "FFFF"

일반적으로 VBA에는 Integer를받을 것으로 예상되는 일부 레거시 API를 제외하고는 최신 시스템에서 "As Integer"를 선언 할 필요가 없습니다.

pcreview 포럼

그리고 마침내 나는 진정으로 찾고 있던 msdn 문서를 찾았습니다 .

전통적으로 VBA 프로그래머는 적은 수의 메모리를 필요로하기 때문에 정수를 사용하여 작은 숫자를 저장했습니다. 그러나 최근 버전에서 VBA는 정수 유형으로 선언 된 경우에도 모든 정수 값을 Long 유형으로 변환합니다. 따라서 Integer 변수를 사용하는 것이 더 이상 성능상의 이점이 없습니다. 실제로 Long 변수는 VBA에서 변환 할 필요가 없기 때문에 약간 더 빠를 수 있습니다.

요약하자면 Integer요즘 타입 을 사용할 이유가 거의 없습니다 . 16 비트 정수를 예상하는 이전 API 호출과 상호 운용 할 필요가 없는 한 .

지적 할 가치가있는 한 가지는 일부 오래된 API 함수가 16 비트 (2 바이트) 정수인 매개 변수를 예상하고 32 비트에 있고 정수를 전달하려고하는 경우 (이미 4 바이트 길이) 참고로 바이트 길이의 차이로 인해 작동하지 않습니다.

지적 해 주신 Vba4All에게 감사드립니다.


다른 답변에서 언급했듯이 int와 long의 실제 차이점은 메모리 공간의 크기와 따라서 저장할 수있는 숫자의 크기입니다.

다음은 이러한 데이터 유형에 대한 전체 문서입니다. http://msdn.microsoft.com/en-us/library/office/ms474284(v=office.14).aspx

정수는 16 비트이며 -32,768과 32,767 사이의 값을 나타낼 수있다

32 비트 2,147,483,647 -2,147,483,648로 나타낼 수

64 비트이고 9 펜 틸리 언처럼 처리 할 수 있는 LongLong 이 있습니다.

이것에 대해 기억해야 할 가장 중요한 것 중 하나는 데이터 유형이 언어와 운영 체제 / 플랫폼에 따라 다르다는 것입니다. VBA 세계에서 long은 32 비트이지만 64 비트 프로세서의 C #에서는 long이 64 비트입니다. 이것은 상당한 혼란을 야기 할 수 있습니다.

VBA는이를 지원하지 않지만 .net 또는 java 또는 기타의 다른 언어로 이동할 때 int16 , int32int64 의 시스템 데이터 유형을 사용하는 것을 선호 하므로 값에 대해 훨씬 더 투명하게 표시 할 수 있습니다. 이러한 데이터 유형에 보관할 수 있습니다.


VBA에는 많은 역사적 수하물이 있습니다.

An Integer은 16 비트 폭이며 16 비트 아키텍처 / 단어 크기가 널리 사용되었을 때 좋은 기본 숫자 유형이었습니다.

A Long는 32 비트 너비이며 가능하면 (IMO)를 사용해야합니다.


이 글은 4 년이되었지만 궁금해서 몇 가지 테스트를 해보았습니다. 주목해야 할 가장 중요한 점은 코더는 항상 변수를 SOMETHING으로 선언 해야한다는 것 입니다. 선언되지 않은 변수는 분명히 최악의 성능을 보였습니다 (선언되지 않은 변수는 기술적으로 Variant)

Long성능이 가장 빠르기 때문에 항상 Long대신 사용하라는 Microsoft의 권장 사항 Integer이 합리적 이라고 생각해야 합니다. 나는에서 true와 동일하다고 생각 Byte하지만 대부분의 코더는 이것을 사용하지 않습니다.

64 비트 WINDOWS 10 노트북의 결과

가변 올림픽

사용 된 코드 :

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

이것은 공간필요성 문제입니다.

어떤 상황에서는 오래 사용하는 것이 필요 합니다. 큰 Excel 파일에서 행을 반복하는 경우 행 번호를 보유하는 변수는 길어야합니다.

그러나 때로는 정수가 문제를 처리 할 수 ​​있고 long을 사용하면 공간 (메모리) 낭비라는 것을 알 수 있습니다 . 개별 변수는 실제로 큰 차이를 만들지 않지만 배열을 다루기 시작하면 큰 차이를 만들 수 있습니다.

  • VBA7에서 정수는 2 바이트이고 long은 4 바이트입니다.

  • 1에서 10 사이의 100 만 개의 숫자 배열이있는 경우 Integer 배열을 사용하면 2MB의 RAM 을 차지하는 반면 긴 배열의 경우 약 4MB의 RAM을 차지합니다 .


@PGSystemTester의 방법을 가져와 잠재적 인 가변성을 제거하기 위해 업데이트했습니다. 루틴에 루프를 배치하면 루틴을 호출하는 데 걸리는 시간 (많은 시간)이 제거됩니다. 또한 이로 인해 발생할 수있는 지연을 제거하기 위해 화면 업데이트를 해제했습니다.

Long 여전히 최고의 성능을 발휘했으며 이러한 결과는 변수 유형의 영향만으로 더 밀접하게 제한되므로 변동의 크기는 주목할 가치가 있습니다.

내 결과 (데스크톱, Windows 7, Excel 2010) :

여기에 이미지 설명 입력

사용 된 코드 :

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

As others already mentioned, a Long may take twice as much space as an Integer. As others also already mentioned, the high capacity of current computers means you will see no difference in performance whatsoever, unless you are dealing with extra extra extra large amounts of data:

Memory

Considering 1 million values, the difference between using Integers versus Longs would be of 2 bytes for each value, so that is 2 * 1 000 000 / 1,024 / 1024 = less than 2 MB of difference in your RAM, which is likely much less than 1% or even 0.1% of your RAM capacity.

Processing

Considering the benchmark done by PGSystemTester's, you can see a difference of 811 - 745 = 66 seconds between Longs and Integers, when processing 10 billion batches of 4 operations each. Reduce the number to 1 million of operations and we can expect 66 / 10 000 / 4 = less than 2ms of difference in execution time.


I personally use Integers and Longs to help readability of my code, particularly in loops, where an Integer indicates the loop is expected to be small (less than 1000 iterations), whereas a Long tells me the loop is expected to be rather large (more than 1000).

Note this subjective threshold is way below the Integer upper limit, I use Longs just to make the distinction between my own definitions of small and large.

참고 URL : https://stackoverflow.com/questions/26409117/why-use-integer-instead-of-long

반응형