2012-03-15 63 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等等...... !!!

相关问题