Long 대신 Integer를 사용하는 이유는 무엇입니까?
vbaOverflow
오류와 관련된 질문을 자주 봅니다 .
내 질문은 integer
모든 숫자 변수 ( double
등 제외 )를 정의하는 대신 변수 선언을 사용하는 이유입니다 long
.
값이 32,767 제한을 초과하지 않는다는 것을 보장 할 수있는 for 루프와 같은 작업을 수행하지 않는 한 성능에 영향을 미치거나 사용하지 않음을 지시하는 다른 무언가가 long
있습니까?
정수 변수는 16 비트 (2 바이트) 숫자로 저장됩니다.
Long (long 정수) 변수는 부호있는 32 비트 (4 바이트) 숫자로 저장됩니다.
따라서 이점은 메모리 공간 감소입니다. Integer는 long이 수행하는 메모리의 절반을 차지합니다. 자, 우리는 2 바이트에 대해 이야기하고 있으므로 TON의 정수를 저장하지 않는 한 실제 차이를 만들지 않을 것입니다.
하지만 A의 32 비트 시스템, 16 비트 정수는 자동으로 작업의 숫자의 더 큰 범위의 혜택없이 오래로 변환됩니다. 오버플로는 여전히 발생하며 많은 메모리가 필요합니다. 성능도 할 수있다 상처 데이터 유형이있다 (매우 낮은 수준)로 변환 할 수 있기 때문이다.
내가 찾던 레퍼런스는 아니지만 ....
내 이해는 기본 VB 엔진이 정수로 선언 된 경우에도 정수를 long으로 변환한다는 것입니다. 따라서 약간의 속도 감소를 확인할 수 있습니다. 나는 이것을 한동안 믿어 왔고 아마도 그것이 위의 진술이 만들어진 이유 일 것입니다. 나는 추론을 요구하지 않았습니다.
이것이 제가 찾고 있던 참고 자료입니다.
간단히 대답하면 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"를 선언 할 필요가 없습니다.
그리고 마침내 나는 진정으로 찾고 있던 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 , int32 및 int64 의 시스템 데이터 유형을 사용하는 것을 선호 하므로 값에 대해 훨씬 더 투명하게 표시 할 수 있습니다. 이러한 데이터 유형에 보관할 수 있습니다.
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
'Programing' 카테고리의 다른 글
class << Ruby를 사용한 self vs self.method : 무엇이 더 낫습니까? (0) | 2020.12.07 |
---|---|
Meteor를 중지하는 방법? (0) | 2020.12.07 |
FailedPreconditionError : Tensorflow에서 초기화되지 않은 사용 시도 (0) | 2020.12.07 |
S3 REST API 및 POST 방법 (0) | 2020.12.06 |
PHP : 값의 길이로 배열 정렬? (0) | 2020.12.06 |