为什么我不能在for循环中使用Int64?

时间:2012-03-15 21:36:54

标签: delphi

我可以为整数值编写for..do进程.. 但我不能写它为int64值。 例如:

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

编译器拒绝编译它,为什么拒绝编译?

4 个答案:

答案 0 :(得分:9)

Delphi编译器还不支持Int64循环计数器。

答案 1 :(得分:5)

for loop中的循环计数器必须是整数(或更小) 这是一种加速for循环执行的优化。

内部Delphi始终使用Int32,因为在x86上,这是可用的最快数据类型 这在手册的深处有记载,但我现在没有方便的链接。

如果您必须拥有64位循环计数器,请使用while..dorepeat..until循环。

答案 2 :(得分:3)

即使编译器在Delphi 7 for-loop(Delphi 7 ???)中允许“int64”,它也可能无法完成迭代全程,直到太阳热死后的某个时间。

那么为什么你不能只使用“整数”?

如果必须使用int64值...那么只需使用“while”循环。

问题解决了:))

答案 3 :(得分:2)

为什么在for循环中使用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;

那么为什么编译器拒绝编译foor循环,我认为没有真正的原因......任何for循环都可以自动转换为while循环...并且预编译器可以在编译之前执行此操作(与其他优化一样)已经完成了... ...我看到的唯一原因是懒人创建了没有思考的编译器。

如果for是优化的,所以它只能使用32位索引,那么如果代码尝试使用64位索引就不能这么优化,那么为什么不让预编译器优化器为我们挑选。 ..它只会给程序员带来不好的形象!!!

我不想让任何人弄脏......

我只是说一些明显的事情......

顺便说一句,并非所有人都会在零(或一个)值上启动一个循环...有时需要在非常大的值上启动它。

总是说,如果你需要做一些固定次数的事情,你最好用循环而不是循环......

我也可以说一些......这两个版本,使用Inc(索引)的for循环和while循环同样快......但是如果你把while循环步骤作为Index:= Index +1;它比较慢;它实际上并不慢,因为预编译器优化器看到并使用Inc(索引)代替...你可以看看是否买了下一个:

// 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的情况下它也会将它调整为Inc(变量)......并且这种低级计算机语言的优化非常明显......

在低级计算机语言中: 正常的add(变量:= variable1 + variable2)意味着两个内存读取加一个总和加上一个内存写入......很多工作 但如果是(变量:=变量+其他变量),则可以优化保持处理器高速缓存内的变量。 此外,如果它是(变量:= variable1 + constant),也可以通过在处理器高速缓存上保持常量来优化它 如果它是(变量:=变量+常量),它们都缓存在处理器缓存上,与其他选项相比非常快,不需要访问RAM。

以这种方式,预编译器优化器做了另一个重要的优化... for-loops索引变量被固定为处理器寄存器......比处理器缓存快得多......

大多数母处理器也进行了额外的优化(在硬件级别,在处理器内部)...一些缓存区域(我们看到的32位变量)被强烈使用存储为特殊寄存器以加强访问...这样的for-loop / while-loop索引就是其中之一...但正如我所说的......大多数母亲AMD采用者(那些使用MP技术的人都这样做)...我还不知道任何英特尔那样做!当多核和超级计算时,这种优化更具相关性......所以也许这就是为什么AMD拥有它而英特尔不是!!!

我只想展示一个“为什么”,还有更多...另一个可能就像索引存储在数据库Int64字段类型等一样简单...有很多原因我我知道还有很多我还不知道...

我希望这有助于理解在Int64索引上进行循环的必要性,以及如何通过正确有效地将循环转换为while循环而不失去速度来实现它。

注意:对于x86编译(不适用于64位编译),请注意Int64在内部作为两个Int32部分进行管理...并且在修改值时需要执行额外的代码,在添加和替换时它非常低,但是在乘法或除法这样的额外是明显的......但是如果你真的需要Int64你需要它,那么还有什么可做......想象一下如果你需要漂浮或双重等等...... !!!