beta 的第三篇心得:深入研究 case 语句 (50分)

Y

Yong

Unregistered / Unconfirmed
GUEST, unregistred user!
有点意思!收!
 
W

wjiachun

Unregistered / Unconfirmed
GUEST, unregistred user!
你的几篇心得我想替你推荐发表了,不知道是否可以?
如果可以请抽空整理一下 :)
 
B

beta

Unregistered / Unconfirmed
GUEST, unregistred user!
to 老猫:
谢谢了,我也想过发表,就是怕人家不要啊:(
QQ 上联系吧,告诉我一点具体的事情。
 

我爱飞

Unregistered / Unconfirmed
GUEST, unregistred user!
Z

zhukewen

Unregistered / Unconfirmed
GUEST, unregistred user!
如果是这样的例子呢?
i := 7;
if i = 1 then
showmessage('i')
else
if i = 100000000 then
showmessage('10000000')
else
showmessage('other');
case语句又如何才有效率呢?
 

小雨哥

Unregistered / Unconfirmed
GUEST, unregistred user!
哈哈哈哈
i:=7;// i Longint
case i of
1:ShowMessage('i');
1000000:showmessage('1000000');
else
showmessage('other')
end;
和楼上的 if 有不同?
当然还可以:
i:=7;
case i of
1:ShowMessage('i');
2..1000:showmessage('2-1000');
// case 子界
1000000:showmessage('1000000');
else
showmessage('other')
end;
不过这和讨论的主题不符。写一则,兼收藏。
 
B

beta

Unregistered / Unconfirmed
GUEST, unregistred user!
to zhukewen:
我知道您的意思,但是我前面已经说过了,当最小项的值和最大项的值之间的差距很大
的时候,Delphi 会用不同的方法进行处理。
我看了一下,当出现您这种极端情况的时候,Delphi 不会建表,而是直接用一种和 if
then
else
if 类似的方法进行处理。也就是说,效率和 if then
else
if 相当。
因此“case语句又如何才有效率呢?”这个问题就清楚了。
to 小雨哥:
你这两种情况的处理和上面一样:)
呵呵,不过要是出现这种情况,最好的办法就是改进设计,进而避免咯:)
 

小雨哥

Unregistered / Unconfirmed
GUEST, unregistred user!
各位老大,请做个测试,虽然这个不说明什么问题,但不妨作为业余游戏啊:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, TypInfo;
type
TMyStrSel = (Beijing, Tianjing, Shanghai, Chongqing);
TForm1 = class(TForm)
Button1: TButton;
ComboBox1: TComboBox;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
t1, t2: Cardinal;
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject);
begin
ComboBox1.Text := 'Chongqing';
with ComboBox1.Itemsdo
begin
Add('Beijing');
Add('Tianjing');
Add('Shanghai');
Add('Chongqing');
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
str: string;
strSel: TMyStrSel;
i: Cardinal;
begin
str := ComboBox1.Text;
i := 429496;//7295;
{MAX:4294967295}
t2 := 0;
t1 := GetTickCount;
strSel := TMyStrSel(GetEnumValue(TypeInfo(TMyStrSel), str));
while i > 0do
begin
case strSel of
Beijing: t2 := GetTickCount;
Tianjing: t2 := GetTickCount;
Shanghai: t2 := GetTickCount;
Chongqing: t2 := GetTickCount;
else
t2 := GetTickCount;
end;
dec(i);
end;
Caption := Format('选择 %s ,计算时间 %u ms', [str, t2 - t1]);
end;
procedure TForm1.Button2Click(Sender: TObject);
var
str: string;
i: Cardinal;
begin
str := ComboBox1.Text;
i := 429496;//7295;
{MAX:4294967295}
t2 := 0;
t1 := GetTickCount;
while i > 0do
begin
if str = 'Beijing' then
t2 := GetTickCount
else
if str = 'Tianjing' then
t2 := GetTickCount
else
if str = 'Shanghai' then
t2 := GetTickCount
else
if str = 'Chongqing' then
t2 := GetTickCount
else
t2 := GetTickCount;
Dec(i);
end;
Caption := Format('选择 %s ,计算时间 %u ms', [str, t2 - t1])
end;
end.
结果是什么?测试后看一看啊,也不知道我的代码有没有写错。
 
B

beta

Unregistered / Unconfirmed
GUEST, unregistred user!
呵呵,小雨哥,你这个例子很说明问题啊,下面是我的测试结果:
(以下时间取 10 次的平均值,单位毫秒)
选择 case 方法 if 方法
Beijing 0.8 30
Tianjing 0.8 47
Shanghai 0.9 65
Chongqing 0.8 85
效率问题很明显的摆在眼前,我就不用多说了[:D]
 
D

DoubleWood

Unregistered / Unconfirmed
GUEST, unregistred user!
TO小雨哥:
你这个比较有些不公平,
strSel := TMyStrSel(GetEnumValue(TypeInfo(TMyStrSel), str));
while i > 0do
begin
case strSel of
...
end;
dec(i);
end;
其中strSel := TMyStrSel(GetEnumValue(TypeInfo(TMyStrSel), str));只做了一次,
而if中的字符串的比较可是做了无数次哦,所以不能说明什么问题。
这个算法的关键是在于把字符转换为有序整数,效率的关键在于转换函数效率。如果
if的时间复杂度是O(n/2),而 case 的时间复杂度是 O(1)。假设转换函数的时间复杂
度也是O(1),记为O'(1)吧。那么整个算法的时间复杂度是O'(1)+O(1),让我们来看小
雨哥的比较,假设他做了X次,那么整时间复杂度应该是是X*(O'(1)+O(1)),然而小雨
哥把程序写成了O'(1)+X*(O(1)),很明显这是个投机取巧的做法,因为实际上O'(1)的
时间要大于O(1)。对于程序设计来说,这种取巧是一种技巧,值得学习,然而对于测试
来说,违背了公平原则。建议修改一下程序:
while i > 0do
begin
strSel := TMyStrSel(GetEnumValue(TypeInfo(TMyStrSel), str));
case strSel of
...
end;
dec(i);
end;
把strSel := TMyStrSel(GetEnumValue(TypeInfo(TMyStrSel), str));
这一句移到循环内,再做测试,这样才是公平的结果[:D]
 
B

beta

Unregistered / Unconfirmed
GUEST, unregistred user!
DoubleWood: 这样才是不公平,我们讨论的是 case 和 if then
else
if 之间的效率
不应该涉及到其他的东西。
如果你想不通,可以直接全部用 整型 来进行比较,一样可以看出效率差异的:)
 
T

tseug

Unregistered / Unconfirmed
GUEST, unregistred user!
毋庸置疑,case的效率无论从哪个方面来说都优于if then
else
if
之所以存在if then
else
if 这样的代码如果排除编程人员的水平因素,完全是因为
if then
else
if 的适用范围远远多于case. 事实上,两者从逻辑上完全等效,采用
那种方式完全取决于编码的代价,尽管case 效率高,但考虑编写代码,对于特定的人
综合工作量来说可能if then
else
if更少一些。另外,对于某些情况下,如果用case
的可读性反而不如if then
else
if。所以,采用那种形式还要具体问题具体分析。
 
C

chillkwanjane

Unregistered / Unconfirmed
GUEST, unregistred user!
case ordinal_type of
.
.
end;
确实比if then
else
效率要高,
但是GetEnumValue(TypeInfo(TMyStrSel), str));
又是在做什么呢,无需进行字符串比较?
 
P

protagonist

Unregistered / Unconfirmed
GUEST, unregistred user!
CASE 与 IF 的比较就好比 WHILE 和 FOR 的比较。
 
C

chillkwanjane

Unregistered / Unconfirmed
GUEST, unregistred user!
我想,既然用得上case那么所有的情况都是已经预知的,其实,如果需要判断的情况稍微
多一点,用首字母hash
case aStr[1] of
'A':
if (aStr = 'ABC') then
begin
end
else
if (aStr = 'ABCD') then
begin
end;
还是比较有效率的,如果需要判断的情况太多,性能要求又太高,就需要寻求更高性能的
算法
 
D

DoubleWood

Unregistered / Unconfirmed
GUEST, unregistred user!
TO beta:
也许是我没有看清楚你的题目,也许是我看了你的第二篇还没回过神来。我以为说的是
字符变成有序类型然后用CASE这种办法和直接用if...then
...的比较,所以得
出不公平的结论。
不过在我看来,就算是比较CASE和if...then
...的效率,小雨哥的程序仍然有失公平。
原因很简单,那就是如果要进行这样的比较,那么在if 比较的时候,不应该使用象字符
串比较这样化时间的操作,因为if...then
...本身花费的时间并不多,相对来说,绝大多
数时间化在了字符比较上,这难道叫公平吗?
 

小雨哥

Unregistered / Unconfirmed
GUEST, unregistred user!
case 循环更改为:
~~~~~~~~~~~~~~~~
while i > 0do
begin
strSel := TMyStrSel(GetEnumValue(TypeInfo(TMyStrSel), str));
case strSel of
...
end;
dec(i);
end;

字符串增加为:
~~~~~~~~~~~~~~~~
with ComboBox1.Itemsdo
begin
Add('Beijing');
Add('Tianjing');
Add('Shanghai');
Add('Chongqing');
Add('Zhongguo');
Add('Hangzhou');
Add('Suibian');
end;

测试结果
~~~~~~~~~~~~~~~~~
选择 case 方法 if 方法
15 40
Beijing 40 25
Tianjing 45 45
Shanghai 60 60
Chongqing 50 70
Zhongguo 35 70
Hangzhou 35 70
Suibian 30 70
 
S

SS2000

Unregistered / Unconfirmed
GUEST, unregistred user!
我觉得大家的讨论有点偏了
如果一段程序的执行时间很长,需要优化,那他的瓶颈
有多少可能是if..then
..else
和case语句造成的?
如果程序运行需要10秒钟,你把if..thne..else
换成
case,或者把case换成if..thne..else
节约几十毫秒
有什么意义?,而且各位的测试不知是如何测试的?
如果一个case语句需要几十毫秒,或者一个10来行
的if..then
..else
需要几十毫秒,那不知各位用的
是什么机器?是386还是286,或者更差是8086,即使
是那些机器,大概也用不了那么多的时间。顺便说一
句,如果用Now函数来计算运行时间,如果运行时间
是秒以上的,还是可用的,如果运行时间是毫秒级的
用这个函数得出的结果是不可靠的,就像100米跑,用
秒表可以分辨两个人的速度,可是如果这一百米是
飞机飞过,一个是800公里/小时,一个是900公里/小时
你的秒表能分得出来吗?
所以通常case或if..then
..else
本身并不是效率的优化对象,
我编程序还基本没有遇到需要优化case或if..then
..else

身的时候,因为case或if..then
..else
本身永远不会成为
瓶颈,因为我们编的是应用程序,除非你的程序就是要处理
case或if..then
..else
本身这种情况,呵呵
 
S

SOHOMO

Unregistered / Unconfirmed
GUEST, unregistred user!
本人倾向于:
if ... then
begin
......
end else

if ... then
begin
......
end else

if ... then
begin
......
end else

if ... then
begin
......
end else

......
 
T

tseug

Unregistered / Unconfirmed
GUEST, unregistred user!
同意SS2000的观点, 如果为了研究一下, 深入讨论有点意义..如果仅仅是为了
对于编码时采用if 还是 case的一个佐证,就没有什么大的意义了。尽管说程序
的细微之处见功夫,但是如果不能够从大处着眼,从全面去衡量一个系统不同
方案的利弊得失,懂得再多的技巧也只能停留在低层次的水平上。。。。
 

Similar threads

顶部