我有一段代码
if (A == B)
{
...
}
else if (A < B)
{
...
}
else // (A > B)
{
...
}
我意识到存在冗余问题,因为在==
和<
的计算中会有一些相同的比特比较。如何优化我的代码以使其更加漂亮和快速?
答案 0 :(得分:1)
您没有指定语言,但根据语言,可以通过多种方式重写
Ruby方式(使用spaceship operator):
case A <=> B
when -1 then... # A < B
when 0 then... # A = B
when 1 then... # A > B
end
Perl,PHP7和Groovy也有相同的运算符。许多其他语言具有类似的运算符或函数,用于cmp
in Python 2, compare
in OCaml and compareTo
in Kotlin之类的组合比较目的。 C#没有该运算符,但它具有IComparable
接口和CompareTo
方法。
VB方式:
Select Case A
Case Is < B
...
Case Is = B
...
Case Is > B
...
End Select
在C,C ++和许多没有CompareTo
方法的C语言中你可以用这种方式
int cmp = (A > B) - (A < B);
switch (cmp)
{
case -1: ...
case 0: ...
case 1; ...
}
Java等许多语言都不允许您直接将比较结果用作数值。在这种情况下,您可以使用signum
function
switch(Integer.signum(A - B))
您可以在C和C ++ like this
中轻松实现signum
功能
这些是高级语言。在装配级别,事情更简单。在x86汇编中只需要进行一次比较,然后根据结果我们会跳转到相应的块,因此它的不 3比较,并且编译器足够聪明以进行优化这个简单的案例。例如:
cmp eax, ebx
je EQUAL_TO ; jump if =
ja GREATER_THAN ; jump if >
; less than case's code
jmp END_CMP
EQUAL_TO:
; equal case's code
jmp END_CMP
GREATER_THAN:
; larger than case's code
END_CMP:
与其他具有比较标志的架构(如ARM或68k)相同......对于没有像MIPS这样的标志的架构,您可能需要再进行一次比较,但绝不需要进行3次比较
MIPS示例:
beq $t0, $t1, EQUAL_TO # $t0 = A, $t1 = B; if ($t0 == $t1) equal();
slt $t0, $t1, $t2 # $t2 = is_less_than = ($t0 < $t1);
beq $t2, $zero, GREATER_THAN # if (!is_less_than) larger();
# "less than" code here
# ...
j END_CMP
EQUAL_TO:
# "equal" code
# ...
j END_CMP
GREATER_THAN:
# "larger" code
# ...
END_CMP:
对于具有条件指令(如ARM或Itanium)的体系结构,并且在if-else块中具有足够简单的主体,您可能甚至不需要跳转
答案 1 :(得分:0)
对于C#,你可以使用一个通用函数,它接受2个值,然后是每个case的lambda动作。
void CompareAndAct<T>(T a, T b, Action fnEqualTo, Action fnLessThan, Action fnGreaterThan) {
var comparison = System.Collections.Generic.Comparer<T>.Default.Compare(a, b);
if (comparison == 0) {
fnEqualTo();
}
else if (comparison < 0) {
fnLessThan();
}
else { //A > B
fnGreaterThan();
}
}
然后你可以按照你想要的那样重复使用它:
CompareAndAct(a,b, () => Console.Writeline("Equal"),() => Console.WriteLine("Less Than", () => Console.WriteLine("Greater Than"));
我不能说我建议这样做,但它确实有效。它不会更快(可能更慢),但我想可以说它是“更高级的”。