呵呵,小雨哥,有时候仅仅是讲道理是不够的,还是根据我常说的
“实践是检验真理的唯一标准”,来一个例子说明问题(见后)
很显然,小雨哥是想告诉我们这样一个事实(我拣个便宜[
]):
给出一个题目:计算从 1 累加到 M 的结果。典型的程序员立刻就
写了一个 for 循环(对应我后面的 Calc1),发现效率不够,于是
zjan521 兄即对其进行汇编优化(对应后面的 Calc0),而小雨哥
则从容的用 ObjectPascal 写出了另一个版本(对应后面的 Calc2)
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
btn1: TButton;
btn2: TButton;
mmo1: TMemo;
procedure btn1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
const
CalcMax = 100000;
CalcTimes = 1000;
type
TCalcFunc = function(Max: DWord): Integer;
// 这是我用汇编优化后的版本,没有考虑特殊情况,否则更慢
function Calc0(Max: DWord): Integer;
asm
mov ecx, eax
xor eax, eax
@loop:
add eax, ecx
dec ecx
jnz @loop
end;
// 典型解法
function Calc1(Max: DWord): Integer;
var
i: Integer;
begin
Result := 0;
for i := 1 to Max do
Result := Result + i;
end;
// 聪明的解法,根本不需要汇编优化,完全用纯 Pascal 写成
function Calc2(Max: DWord): Integer;
begin
Result := (1 + Max) * Max div 2;
end;
// 测试函数,让制定的计算方法多执行几次,以拉开时间差距
function TestCalc(CalcFunc: TCalcFunc
var Count: Integer): DWord;
var
i: Integer;
begin
Result := GetTickCount;
for i := 1 to CalcTimes do
Count := CalcFunc(CalcMax);
Result := GetTickCount - Result;
end;
// 输出测试结果
procedure TForm1.btn1Click(Sender: TObject);
var
Count: Integer;
begin
mmo1.Lines.Add(Format('Calc0 (%dms): %d.', [TestCalc(Calc0, Count), Count]));
mmo1.Lines.Add(Format('Calc1 (%dms): %d.', [TestCalc(Calc1, Count), Count]));
mmo1.Lines.Add(Format('Calc2 (%dms): %d.', [TestCalc(Calc2, Count), Count]));
end;
end.
最后结果如下:
Calc0 (451ms): 705082704. // 汇编优化
Calc1 (641ms): 705082704. // 典型解法
Calc2 (0ms): 705082704. // 聪明解法
很显然,也许本人功力不足,没有办法把 Calc0 优化的更快,就算 zjan521 兄
有能力将其速度再提高一倍(似乎不太可能),那也是 225ms,和 Calc2 的速度
还是没有办法相比。
道理应该很明显了,我就不多费“唇舌”了[
]