如何优化表格声明" if(A == B){...} else if(A< B){...} else {....}"

时间:2014-05-28 17:39:27

标签: optimization premature-optimization

我有一段代码

if (A == B)
{
    ...
}
else if (A < B)
{
    ... 
}
else // (A > B)
{
    ...
}

我意识到存在冗余问题,因为在==<的计算中会有一些相同的比特比较。如何优化我的代码以使其更加漂亮和快速?

2 个答案:

答案 0 :(得分:1)

您没有指定语言,但根据语言,可以通过多种方式重写

Ruby方式(使用spaceship operator):

case A <=> B
    when -1 then... # A < B
    when  0 then... # A = B
    when  1 then... # A > B
end

PerlPHP7和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"));

我不能说我建议这样做,但它确实有效。它不会更快(可能更慢),但我想可以说它是“更高级的”。

相关问题