关于交换两个整数(不借助第三个临时数)...
2009-10-21 11:40
204 查看
不借助第三个临时数交换两个整数,无外乎进行所谓的数字魔术,或借助寄存器实现,但除此外还有一种“巧妙的”方法:通过 XOR 变换实现――不过论其本质,还是所谓的数字魔术,:-) ...
随手测试了下 数字魔术、借助寄存器(纯 Asm 实现) 及 XOR变换 的效率,耗时显示,纯 Asm 实现 < XOR变换 < 数字魔术――结果当然不出意料,纯Asm实现 比另两者快很多。
Delphi 测试代码:
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils, Windows;
var
I, J, K, M, N: Integer;
begin
// the BASE arithmetic ...
M := 1;
N := 2;
K := GetTickCount;
for I := 0 to 5000 do
begin
for J := 0 to 5000 do
begin
M := M + N;
N := M - N;
M := M - N;
end;
end;
K := GetTickCount - K;
Writeln(K, ';', M, ';', N);
ReadLn;
// use Registers ...
M := 1;
N := 2;
K := GetTickCount;
asm // EAX: 循环计数; ECX: I; EDX: J; EBX: M; EDI: N
PUSH EBX
PUSH EDI
MOV EBX, M
MOV EDI, N
MOV EAX, 5000
MOV ECX, 0
@Loop1: CMP ECX, EAX
JA @Loop1End
MOV EDX, 0
@Loop2: CMP EDX, EAX
JA @Loop2End
XCHG EBX, EDI
INC EDX
JMP @Loop2
@Loop2End: INC ECX
JMP @Loop1
@Loop1End: MOV M, EBX
MOV N, EDI
POP EDI
POP EBX
end;
K := GetTickCount - K;
Writeln(K, ';', M, ';', N);
ReadLn;
// Now XOR ...
M := 1;
N := 2;
K := GetTickCount;
for I := 0 to 5000 do
begin
for J := 0 to 5000 do
begin
M := M xor N;
N := N xor M;
M := M xor N;
end;
end;
K := GetTickCount - K;
Writeln(K, ';', M, ';', N);
ReadLn;
end.
P.S:以 VC 6.0 + SP6 测试了同样效果的代码,Release 下其结果明显快于 Delphi 的数字魔术(但仍比 纯Asm实现 慢一些) ...Delphi 优化器确实较差,没办法。
VC 测试代码:
#include <iostream>
#include <windows.h>
void main()
{
int I, J, K, M, N;
M = 1;
N = 2;
K = GetTickCount();
for (I = 0; I <= 5000; I++)
{
for (J = 0; J <= 5000; J++)
{
M = M + N;
N = M - N;
M = M - N;
}
}
K = GetTickCount() - K;
printf("%d;%d;%d\n", K, M, N);
}
本文出自 “ADelphiCoder” 博客,请务必保留此出处http://adelphicoder.blog.51cto.com/983561/214667
随手测试了下 数字魔术、借助寄存器(纯 Asm 实现) 及 XOR变换 的效率,耗时显示,纯 Asm 实现 < XOR变换 < 数字魔术――结果当然不出意料,纯Asm实现 比另两者快很多。
Delphi 测试代码:
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils, Windows;
var
I, J, K, M, N: Integer;
begin
// the BASE arithmetic ...
M := 1;
N := 2;
K := GetTickCount;
for I := 0 to 5000 do
begin
for J := 0 to 5000 do
begin
M := M + N;
N := M - N;
M := M - N;
end;
end;
K := GetTickCount - K;
Writeln(K, ';', M, ';', N);
ReadLn;
// use Registers ...
M := 1;
N := 2;
K := GetTickCount;
asm // EAX: 循环计数; ECX: I; EDX: J; EBX: M; EDI: N
PUSH EBX
PUSH EDI
MOV EBX, M
MOV EDI, N
MOV EAX, 5000
MOV ECX, 0
@Loop1: CMP ECX, EAX
JA @Loop1End
MOV EDX, 0
@Loop2: CMP EDX, EAX
JA @Loop2End
XCHG EBX, EDI
INC EDX
JMP @Loop2
@Loop2End: INC ECX
JMP @Loop1
@Loop1End: MOV M, EBX
MOV N, EDI
POP EDI
POP EBX
end;
K := GetTickCount - K;
Writeln(K, ';', M, ';', N);
ReadLn;
// Now XOR ...
M := 1;
N := 2;
K := GetTickCount;
for I := 0 to 5000 do
begin
for J := 0 to 5000 do
begin
M := M xor N;
N := N xor M;
M := M xor N;
end;
end;
K := GetTickCount - K;
Writeln(K, ';', M, ';', N);
ReadLn;
end.
P.S:以 VC 6.0 + SP6 测试了同样效果的代码,Release 下其结果明显快于 Delphi 的数字魔术(但仍比 纯Asm实现 慢一些) ...Delphi 优化器确实较差,没办法。
VC 测试代码:
#include <iostream>
#include <windows.h>
void main()
{
int I, J, K, M, N;
M = 1;
N = 2;
K = GetTickCount();
for (I = 0; I <= 5000; I++)
{
for (J = 0; J <= 5000; J++)
{
M = M + N;
N = M - N;
M = M - N;
}
}
K = GetTickCount() - K;
printf("%d;%d;%d\n", K, M, N);
}
本文出自 “ADelphiCoder” 博客,请务必保留此出处http://adelphicoder.blog.51cto.com/983561/214667
相关文章推荐
- 不借助第三个变量交换两个整数
- 不借助第三个变量交换两个整数的值
- 为什么异或运算可以实现两个整数的交换,而无需借助第3个临时变量
- 不借助第三个变量交换两个整数
- 为什么异或运算可以实现两个整数的交换,而无需借助第3个临时变量
- 不借助临时变量交换两个变量的值
- 不借助第三个变量实现两个变量交换的思考
- 不借助第三个变量交换两个数值类型变量的值
- 不借助第三个变量交换两个变量的值
- 基于JAVA的不借助第三个变量实现交换两个变量的值的小代码
- 关于两个整数的交换的几种写法
- 不借助第三个变量实现两个变量之间的值传递和交换
- 不借用临时变量交换两个整数的值
- 交换两个整数值,不用临时变量
- 1. 给定两个整形变量的值,将两个值的内容进行交换。 2. 不允许创建临时变量,交换两个数的内容(附加题) 3. 求10 个整数中最大值。 4. 写一个函数返回参数二进制中 1 的个数
- 不借助第三个变量,交换两个变量值的3种方式
- 关于交换两个变量的不用第三个变量 异或的问题
- 不借助第三个变量交换两个值
- 不借助第三个变量实现两个变量交换的思考
- 不实用第三个临时变量,交换两个int变量的值