Dlaczego warto używać Integer zamiast Long?
Często widzę pytania dotyczące Overflow
błędów z vba .
Moje pytanie brzmi Dlaczego używać deklaracji zmiennej integer
zamiast tylko definiować wszystkie zmienne numeryczne (wyłączając double
itd.) jako long
?
Jeśli nie wykonujesz operacji jak w pętli for, gdzie możesz zagwarantować, że wartość nie przekroczy limitu 32,767, czy jest jakiś wpływ na wydajność lub coś innego, co nakazywałoby nie używać long
?
7 answers
Zmienne całkowite są przechowywane jako 16-bitowe (2-bajtowe) liczby
Zmienne Long (long integer) są przechowywane jako Podpisane 32-bitowe (4-bajtowe) liczby
Więc, korzyść jest w zmniejszonej przestrzeni pamięci. Liczba całkowita zajmuje połowę pamięci, którą robi długi. Teraz mówimy o 2 bajtach, więc nie będzie to miało realnej różnicy dla poszczególnych liczby całkowite, to tylko problem, gdy masz do czynienia z tonami liczb całkowitych (np. duże tablice) i użycie pamięci jest krytyczne.
ale na 32 system bitowy, zmniejszenie o połowę zużycia pamięci wiąże się z kosztem wydajności. Gdy procesor faktycznie wykonuje pewne obliczenia z 16-bitową liczbą całkowitą( np. zwiększając licznik pętli), wartość po cichu jest konwertowana do tymczasowego długiego bez korzyści z większego zakresu liczb do pracy z. Przelewy nadal się dzieje, a rejestr, którego procesor używa do przechowywania wartości do obliczeń, zajmie taką samą ilość pamięci (32 bity) w każdym przypadku. wydajność może być nawethurt ponieważ typ danych musi zostać przekonwertowany (na bardzo niskim poziomie).
Nie Referencja, której szukałem, ale....
Rozumiem, że podstawowy silnik VB konwertuje liczby całkowite na długie, nawet jeśli jest zadeklarowany jako liczba całkowita. Dlatego niewielka prędkość spadek można zauważyć. Wierzyłem w to od jakiegoś czasu i być może dlatego też powyższe stwierdzenie zostało złożone, nie prosiłem o uzasadnienie.
To jest odniesienie, którego szukałem.
Krótka odpowiedź, w systemach 32-bitowych 2-bajtowe liczby całkowite są konwertowane na 4-bajtowe Longi. Naprawdę nie ma innego sposobu, aby odpowiednie bity poprawnie liczyły do każdej formy przetwarzania. Rozważmy następujące
MsgBox Hex(-1) = Hex(65535) ' = True
Oczywiście -1 Nie równa się 65535, ale komputer zwraca poprawną odpowiedź, mianowicie "FFFF" = "FFFF"
Jednak gdybyśmy przymus -1 do długiego pierwszego mielibyśmy prawo odpowiedź (65535 jest większy niż 32k jest automatycznie długi)
MsgBox Hex(-1&) = Hex(65535) ' = False
"FFFFFFFF" = "FFFF"
Ogólnie nie ma sensu w VBA deklarować "jako liczbę całkowitą" w nowoczesnym systemów, z wyjątkiem niektórych starszych API, które oczekują, że otrzymają Liczba całkowita.
I w końcu znalazłem dokumentację msdn , której naprawdę naprawdę Szukałem.
Tradycyjnie, Programiści VBA używali liczb całkowitych do przechowywania małych liczby, ponieważ wymagały mniej pamięci. W najnowszych wersjach, jednak VBA konwertuje wszystkie wartości całkowite na typ Long, nawet jeśli są zadeklarowana jako typ Integer. Więc nie ma już przewagi nad wydajnością do użycia zmiennych całkowitych; w fakt, długie zmienne mogą być nieco szybciej, bo VBA nie musi ich konwertować.
aby wyjaśnić na podstawie komentarzy: liczby całkowite nadal wymagają mniej pamięci do przechowywania - duża tablica liczb całkowitych będzie potrzebować znacznie mniej pamięci RAM niż długa tablica o tych samych wymiarach. Jednak ponieważ procesor musi pracować z 32-bitowymi kawałkami pamięci, VBA konwertuje liczby całkowite na Longi tymczasowo podczas wykonywania obliczeń
Więc w podsumowanie, obecnie nie ma prawie żadnego powodu, aby używać typu Integer
. chyba że musisz przeplatać się ze starym wywołaniem API, które oczekuje 16-bitowego int, lub pracujesz z dużymi tablicami małych liczb całkowitych, a pamięć jest na wagę złota.
Warto zwrócić uwagę na to, że niektóre stare funkcje API mogą oczekiwać parametrów, które są 16-bitowymi (2-bajtowymi) liczbami całkowitymi, a jeśli jesteś na 32-bitowym i próbujesz przekazać liczbę całkowitą (która jest już 4-bajtową) przez odniesienie do niego nie będzie działać z powodu różnicy w długości bajtów.
Dzięki Vba4All za wskazanie tego.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-04-17 11:16:25
Jak zauważono w innych odpowiedziach, rzeczywistą różnicą między int i long jest wielkość jego przestrzeni pamięci, a tym samym wielkość liczby, którą może pomieścić.
Oto pełna dokumentacja tych typów danych http://msdn.microsoft.com/en-us/library/office/ms474284(v=office. 14). aspx
An Integer mA 16 bitów i może reprezentować wartość od -32,768 do 32,767
A Long jest 32 bitami i może reprezentować -2,147,483,648 do 2,147,483,647
I jest LongLong, który ma 64 bity i może obsłużyć jak 9 pentilion
Jedną z najważniejszych rzeczy, o których należy pamiętać, jest to, że typy danych różnią się zarówno językiem, jak i systemem operacyjnym / platformą. W Twoim świecie VBA long to 32 bity, ale w c# na 64 bitowym procesorze long to 64 bity. Może to wprowadzić znaczne zamieszanie.
Chociaż VBA nie ma dla niego wsparcia, gdy przeniesiesz się do innego języka w. NET lub java lub inne, I dużo woli używać systemowych typów danych int16, int32 i int64 co pozwala mi b znacznie bardziej przejrzyste o wartościach, które mogą być przechowywane w tych typach danych.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-05-09 19:30:09
Mimo, że ten post ma cztery lata, byłem ciekawy tego i przeprowadziłem kilka testów. Najważniejszą rzeczą do odnotowania jest to, że koder powinien zawsze deklaruj zmienną jako coś. Nierejestrowane zmienne wyraźnie wykonywały najgorsze (nierejestrowane są technicznie Variant
)
Long
zrobił to najszybciej, więc muszę myśleć, że zalecenie Microsoftu, aby zawsze używać Long
zamiast Integer
ma sens. Zgaduję, że to samo co z Byte
, ale większość programistów nie używaj tego.
WYNIKI NA 64-BITOWYM LAPTOPIE Z SYSTEMEM WINDOWS 10
Użyty Kod:
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-07 07:02:32
VBA ma dużo historycznego bagażu.
An Integer
ma szerokość 16 bitów i był dobrym domyślnym typem liczbowym w czasach, gdy przeważała Architektura 16 bitowa/Rozmiar słowa.
A Long
ma szerokość 32 bitów i (IMO) powinna być używana wszędzie tam, gdzie jest to możliwe.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-16 16:30:37
To jest przestrzeń vs konieczność problem.
W niektórych sytuacjach jest to konieczność użycia długiego. Jeśli przeciągasz wiersze w dużym pliku excel, zmienna, która zawiera numer wiersza, powinna być długa.
Jednak czasami będziesz wiedział, że liczba całkowita poradzi sobie z Twoim problemem i użycie long byłoby stratą przestrzeni (Pamięci). Poszczególne zmienne naprawdę nie robią wielkiej różnicy, ale kiedy zaczniesz radzić sobie z tablicami, to może zrobić wielką różnicę.
-
W VBA7 liczby całkowite to 2 bajty, A długości to 4 bajty
Jeśli macie tablicę 1 miliona liczb od 1 do 10, użycie tablicy całkowitej zajmowałoby około 2MB pamięci RAM, w porównaniu do około 4MB pamięci RAM dla długiej tablicy.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-22 05:30:25
Wziąłem metodę @ PGSystemTester i zaktualizowałem ją, aby usunąć pewną potencjalną zmienność. Poprzez umieszczenie pętli w procedurach, usuwa to czas potrzebny na wywołanie procedury (co jest dużo czasu). Wyłączyłem również aktualizowanie ekranu, aby usunąć wszelkie opóźnienia, które może to spowodować.
Long
nadal wykonywane najlepiej, a ponieważ wyniki te są ściślej ograniczone do wpływu samych typów zmiennych, wielkość zmienności jest warta odnotowania.
Moje wyniki (pulpit, Windows 7, Excel 2010):
Użyty kod:
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-06-27 00:09:24
Jak już wspomnieli inni, a Długi niech zajmuje dwa razy więcej miejsca niż liczba całkowita. Jak już wspomnieli inni, duża pojemność obecnych komputerów oznacza, że nie zobaczysz żadnej różnicy w wydajności , chyba że masz do czynienia z dodatkowymi, dodatkowymi, dodatkowymi ilościami danych:
Pamięć
Biorąc pod uwagę 1 milion wartości , Różnica między używaniem liczb całkowitych a długich wynosiłaby 2 bajty dla każdej wartości, więc jest to 2 * 1 000 000 / 1,024 / 1024 = mniej niż 2 MB różnicy w pamięci RAM, co prawdopodobnie jest znacznie mniejsze niż 1% lub nawet 0,1% pojemności pamięci RAM.
Przetwarzanie
Biorąc pod uwagę benchmark wykonany przez PGSystemTester, można zobaczyć różnicę 811 - 745 = 66 sekund między długami i liczbami całkowitymi, podczas przetwarzania 10 miliardów partii po 4 operacje każda. Zmniejsz liczbę do 1 miliona operacji i możemy się spodziewać 66 / 10 000 / 4 = mniej niż 2 ms różnicy w czasie wykonania .
Ja osobiście używam liczb całkowitych i długich, aby pomóc w czytelności mojego kodu , szczególnie w pętlach, gdzie liczba całkowita wskazuje, że pętla ma być mała (mniej niż 1000 iteracji), podczas gdy Long mówi mi, że pętla ma być raczej duża (więcej niż 1000).
Uwaga ten subiektywny próg jest znacznie poniżej górnej granicy liczby całkowitej, używam długich tylko do rozróżnienia między moimi własnymi definicjami małych i dużych.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-08-24 13:32:03