2012-03-15 14 views
7

Mogę napisać proces for..do dla wartości całkowitej. Ale nie mogę zapisać tego dla wartości int64. Na przykład:Dlaczego nie mogę użyć Int64 w pętli for?

var 
    i:int64; 
begin 
    for i:=1 to 1000 do 
end; 

Kompilator odmawia skompilować to, dlaczego odmówić?

+3

Definiowanie "en error". – simchona

+0

Nie mogę zobaczyć błędu. Również program nie można uruchomić .. – musti

+2

+1, ponieważ jest to pytanie akademickie, widzę tak i tak zachowanie. Spodziewałam się, że zadziała, ale nie ... dlaczego tak się zastanawiam. Zamiast "naprawdę potrzebuję wykonać trylionów iteracji w moim rodzaju pętli". – Johan

Odpowiedz

3

Nawet jeśli kompilator zrobił pozwolić „Int64” w Delphi 7 dla pętli (Delphi ???), to prawdopodobnie nie będzie kompletny iteracja pełnym zakresie aż kiedyś po śmierci cieplnej słońce.

Dlaczego więc nie możesz po prostu użyć "liczby całkowitej"?

Jeśli musisz musi użyć wartości int64 ... następnie po prostu użyj pętli "while".

Problem rozwiązany :)

+0

Ale muszę tak postąpić. Ponieważ używam łańcucha o długości 3 miliardów. Jak mogę to napisać: dla i: = 1 do 30000000000? – musti

+0

Użyj pętli 'while', np .:' var I: Int64; I: = 1; podczas gdy ja <= 30000000000 zaczynam ...; Inc (I); koniec; ' –

+1

3-miliardowy ciąg znaków? Bardzo dziwnie się z tym pracuje. –

9

Kompilator Delphi po prostu nie obsługuje jeszcze Int64 liczniki pętli.

5

Liczniki pętli w for loop muszą być liczbami całkowitymi (lub mniejszymi). Jest to optymalizacja, która przyspiesza wykonywanie pętli for.

Wewnętrznie Delphi zawsze używa Int32, ponieważ na x86 jest to najszybszy dostępny typ danych.
Jest to udokumentowane gdzieś głęboko w podręczniku, ale nie mam teraz w tej chwili odpowiedniego linku.

Jeśli masz , musisz mieć licznik pętli 64-bitowej, użyj pętli while..do lub repeat..until.

2

Dlaczego używać Int 64 na pętli for?

łatwo odpowiedzieć:

  • Nie ma potrzeby, aby zrobić wiele iteracji potrzebować Int64, zrób pętlę od 5E9 do 5E9 + 2 (w sumie trzy iteracji).
  • To jest tak, że wartości na iteracji są większe niż to, co Int32 może pomieścić

przykład:

procedure Why_Int64_Would_Be_Great_On_For_Loop; 
const 
    StartValue=5000000000; // Start form 5E9, 5 thousand millons 
    Quantity=10; // Do it ten times 
var 
    Index:Int64; 
begin 
    for Index:=StartValue to StartValue+Quantity-1 
    do begin // Bla bla bla 
      // Do something really fast (only ten times) 
     end; 
end; 

Ten kod weźmie w ogóle czasu, to jest tak, że wartość indeksu potrzebie być daleko niż 32-bitowy limit całkowity.

Rozwiązaniem jest to zrobić za pomocą pętli while:

procedure Equivalent_For_Loop_With_Int64_Index; 
const 
    StartValue=5000000000; // Start form 5E9, 5 thousand millons 
    Quantity=10; // Do it ten times 
var 
    Index:Int64; 
begin 
    Index:=StartValue; 
    while Index<=StartValue+Quantity 
    do begin // Bla bla bla 
      // Do something really fast (only ten times) 
      Inc(Index); 
     end; 
end; 

Więc dlaczego kompilator odmawia skompilować pętlę Foor widzę żadnego powodu ... każdy pętli mogą być automatycznie tłumaczone na język pętla while ... i prekompilator może to zrobić przed kompilatorem (tak jak inne optymalizacje) ... jedyny powód, dla którego widzę, to leniwi ludzie, którzy tworzą kompilator, który nie myślał o tym.

Jeśli dla jest zoptymalizowany, więc może korzystać tylko z indeksu 32-bitowego, to jeśli kod próbuje użyć indeksu 64-bitowego, nie może być zoptymalizowany, więc czemu nie pozwolić, by optymalizator pre-kompilatora wyszukał to dla nas ... tylko daje zły obraz programistom !!!

Nie chcę, aby ktokolwiek ungry ...

Ja tylko po prostu powiedzieć coś oczywistego ...

Nawiasem mówiąc, nie wszyscy ludzie zaczynają pętlę Foor na zero (lub jeden) wartości ... czasami trzeba zacząć od naprawdę dużych wartości.

Jest zawsze dobrze powiedział, że jeśli trzeba coś zrobić określoną liczbę razy ty najlepszego wykorzystania dla pętli zamiast pętli while ...

też mogę coś powiedzieć ... takich dwóch wersjach pętla for i while, która używa Inc (Index) są równie szybkie ... ale jeśli umieścisz krok pętli while jako Index: = Index + 1; jest wolniej; to naprawdę nie jest wolniejsze, ponieważ pre-kompilator optimizator zobaczyć, że i używać Inc (Indeks) zamiast ... można sprawdzić, czy kupić robi następny:

// I will start the loop from zero, not from two, but i first do some maths to avoid pre-compiler optimizator to convert Index:=Index+Step; to Inc(Index,Step); or better optimization convert it to Inc(Index); 
Index:=2; 
Step:=Index-1; // Do not put Step:=1; or optimizator will do the convertion to Inc() 
Index:=Step-2; // Now fix, the start, so loop will start from zero 
while Index<1000000 // 1E6, one millon iterations, from 0 to 999999 
do begin 
     // Do something 
     Index:=Index+Step; // Optimizator will not change this into Inc(Index), since sees that Step has changed it's value before 
    end; 

optymalizator widać zmienna nie zmieniają swoją wartość, więc może go przekonwertować na stałą, a następnie na przypisanie przyrostu, jeśli dodasz stałą (zmienna: = stała + zmienna), to zoptymalizuje ją do wartości Inc (zmienna, stała) iw przypadku, gdy zobaczy taką stałą 1, będzie również optims it to Inc (variable) ... i takie optymizacje w niskim poziomie języka komputerowego są bardzo zauważalne ...

W języku niskim poziomie komputerowym: Normalne dodanie (zmienna: = zmienna1 + zmienna2) implikuje dwa odczyty w pamięci plus jedna suma plus e memory write ... dużo pracy Ale jeśli jest (zmienna: = zmienna + inna zmienna), może być zoptymalizowana przechowująca zmienna wewnątrz pamięci podręcznej procesora. Również jeśli jest to (zmienna: = stała1 + stała), można ją również zoptymalizować, utrzymując stałą wartość na pamięci podręcznej procesora. A jeśli tak (zmienna: = zmienna + stała), oba są buforowane na pamięć podręczną procesora, więc ogromnie szybkie porównanie przy innych opcjach nie jest potrzebny dostęp do pamięci RAM.

w ten sposób wstępnie kompilatora optymalizator zrobić kolejny ważny optymalizacji ... for-pętle zmienne indeksowe są przechowywany jako rejestry procesora ... dużo bardziej szybciej niż procesor cache ...

Most procesor matki zrobić dodatkowy optymalizacja (na poziomie sprzętowym, wewnątrz procesora) ... niektóre obszary pamięci podręcznej (dla nas zmienne 32-bitowe), które są intensywnie używane, są przechowywane jako rejestry specjalne w celu zapewnienia dostępu ... i takiej pętli for-loop/while Indeksy są jednym z nich ... ale jak powiedziałem .. większość procesorów AMD matka (te, które używa technologii MP robi to) ... nie znam jeszcze żadnego Intel, który to robi !!! taka optymalizacja jest bardziej odpowiednia w przypadku wielordzeniowych i superkomputerowych ... więc może to jest powód, dla którego AMD ma to i Intel nie !!!

Chcę tylko pokazać jedno "dlaczego", jest o wiele więcej ... inny może być tak prosty, jak indeks jest przechowywany w bazie danych typu pola Int64, itp ... jest wiele powodów wiem i jeszcze więcej nie wiedziałem jeszcze ...

Mam nadzieję, że pomoże to zrozumieć potrzebę zrobienia pętli na indeksie Int64, a także jak to zrobić bez utraty prędkości, poprawnie i sprawnie konwertując pętlę w pętla while.

Uwaga: W przypadku kompilacji x86 (nie w przypadku kompilacji 64-bitowej) należy pamiętać, że Int64 jest zarządzany wewnętrznie jako dwie części Int32 ... a podczas modyfikowania wartości istnieje dodatkowy kod do wykonania, w przypadku dodawania i podrzędnych jest bardzo niski, ale na mnożnikach lub podziałach takie dodatkowe są zauważalne ...ale jeśli naprawdę potrzebujesz Int64, potrzebujesz go, więc co jeszcze możesz zrobić ... i wyobrazić sobie, że potrzebujesz float lub double, etc ... !!!

Powiązane problemy