2012-03-15 112 views
7

我可以寫for..do進程的整數值.. 但我不能寫它的int64值。 例如:爲什麼我不能在for循環中使用Int64?

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

編譯器拒絕編譯這個,它爲什麼拒絕呢?

+3

定義「en error」。 – simchona 2012-03-15 21:38:30

+0

我不能看到一個error.also程序無法啓動.. – musti 2012-03-15 21:46:40

+2

+1,因爲這是一個學術問題,我看到某某行爲。我會預料到它的工作,但它不......這是我爲什麼想知道。而不是'我真的需要在我的循環中做數萬億次的迭代'這種問題。 – Johan 2012-03-16 11:59:10

回答

3

即使編譯器允許「的Int64」德爾福7環(德爾福 ???),它可能會通過全方位的不完整的迭代,直到某個熱死後太陽。

那麼,爲什麼你不能只使用「整數」?

如果你必須使用int64的值...那麼只需使用「while」循環來代替。

問題解決了:)

+0

但我必須這樣做,因爲我使用的字符串是30億長度。如何寫這個:對於我:= 1到30000000000? – musti 2012-03-15 21:51:15

+0

使用'while'循環,例如:'var I:Int64; I:= 1;而我<= 30000000000確實開始......;公司(I);結束;' – 2012-03-15 23:06:54

+1

30億字符串?聽起來很奇怪。 – 2012-03-15 23:17:48

9

的Delphi編譯器根本不支持的Int64循環計數器呢。

5

for loop中的循環計數器必須是整數(或更小)。
這是一個優化,以加快執行for循環。

內部Delphi總是使用Int32,因爲在x86上這是可用的最快的數據類型。
這是記錄在手冊的深處,但我現在沒有方便的鏈接。

如果必須有64位循環計數器,使用while..dorepeat..until循環。

2

爲什麼要在for-loop上使用Int64?

容易回答:

  • 沒有必要做大量的迭代需要的Int64的,只是做從5E9一個循環5E9 + 2(三次迭代中總)。
  • 這僅僅是迭代的值比的Int32可以容納

一個例子更大:

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; 

該代碼會採取任何時候都,它只是索引值需要遠遠超過32位整數限制。

的解決方案是用一個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; 

那麼爲什麼編譯器拒絕編譯福爾循環,我認爲沒有真正的理由......任何for循環,可以自動翻譯成一個while循環......並且預編譯器可以在編譯器之前這樣做(就像完成其他優化一樣)......我看到的唯一原因是創建編譯器的懶惰的人沒有想到它。

如果for是優化的,所以它只能使用32位索引,那麼如果代碼嘗試使用64位索引,它不能被如此優化,那麼爲什麼不讓預編譯器優化器爲我們改變......它只會給程序員帶來不好的形象!

我不想讓任何人ungry ...

我只說幾句話明顯...

順便說,並不是所有的人開始零(或一個)值的福爾循環...有時需要以真正巨大的價值開始它。

據永諾說,如果你需要做的事情的固定次數你循環而不是while循環最好使用...

此外,我能說些什麼......這樣的兩個版本, for循環和使用Inc(Index)的while循環同樣快速......但是如果您將while循環步驟設置爲Index:= Index + 1;它比較慢;這是真的不慢,因爲預編譯optimizator看到並使用公司(指數),而不是...你可以看到,如果買在做下一個:

// 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; 

優化可以看到一個變量不改變它的價值,所以它可以將其轉換爲一個常量,然後在增量賦值時添加一個常量(變量:=變量+常量),它將優化到Inc(變量,常量),並且在它看到這個常量爲1的情況下,它也會optimes它來公司(可變)...和在低的水平的計算機語言例如optimizatons非常都明顯...

在低電平計算機語言: 一個正常的加載(變量:=變量1 +變量2)意味着兩個存儲器讀取加上一筆總和e memory memory ...很多工作 但是如果是(變量:=變量+其他變量),它可以在處理器緩存內優化保持變量。 此外,如果它是一個(變量:=變量1 +常量),它也可以通過在處理器緩存上保持常量來優化 如果它是(變量:=變量+常量),則緩存在處理器緩存上,與其他選項一樣,不需要訪問RAM。

在這種方式預編譯器優化做的另一個重要的優化... for循環索引變量holded者處理器寄存器...比處理器高速緩存更快更多...

大多數母親處理器做一個額外的優化(在硬件級別,在處理器內部)......一些被強制使用的緩存區域(我們的32位變量)被存儲爲特殊的寄存器以緊固訪問......並且這樣的for-loop/while-loop索引就是其中之一...但正如我所說的......大多數母親的AMD處理器(使用MP技術的處理器都是這樣做的)......我還不知道有哪個英特爾這樣做!這樣的優化在多核和超級計算時更具相關性......所以也許這就是AMD爲什麼會這麼做的原因,而英特爾不是!

我只想顯示一個「爲什麼」,還有更多...另一個可以像索引存儲在數據庫Int64字段類型等一樣簡單...有很多原因我知道,還有更多我還不知道......

我希望這將有助於瞭解需要做一個Int64索引上的循環,以及如何做到這一點,而不會因爲正確高效地將循環轉換爲一個while循環。

注意:對於x86編譯(不適用於64位編譯)請注意,Int64在內部作爲兩個Int32部件進行管理......並且在修改值時需要額外的代碼,在增加和下降時它非常低,但在乘法或分裂這種額外的是很明顯的...但是如果你真的需要Int64,那麼還有什麼可以做的......並且想象一下,如果你需要float或者double等等...... !!!

相關問題