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?

Author: Gareth, 2014-10-16

7 answers

Zmienne całkowite są przechowywane jako 16-bitowe (2-bajtowe) liczby

Office VBA Reference

Zmienne Long (long integer) są przechowywane jako Podpisane 32-bitowe (4-bajtowe) liczby

Office VBA Reference

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.

ozgrid fora

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.

forum pcreview

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.

 130
Author: RubberDuck,
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.

 13
Author: Patrick,
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

Olimpiada Zmienna

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
 9
Author: PGSystemTester,
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.

 8
Author: Alex K.,
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.

 4
Author: Alter,
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):

Tutaj wpisz opis obrazka

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
 3
Author: AJD,
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.

 1
Author: Ama,
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