哪个更有效率。 if(a-b> 0)或if(a> b)

时间:2014-06-22 02:48:34

标签: algorithm performance

这可能是一个简单的问题。

我想知道2个语句中的哪个将花费更少的时间来执行。

if ( a - b > 0 ) or if ( a > b )

在第一种情况下,必须计算差值,然后必须将其与0进行比较,而在第二种情况下,直接比较a和b。

感谢。

4 个答案:

答案 0 :(得分:2)

正如Keith Thompson指出的那样,两者相同。例如,如果ab未签名,则a-b始终为非负数,使该语句等同于if(a != b)

无论如何,我做了一个不切实际的测试:

int main() {
    volatile int a, b;

    if(a-b>=0)
        printf("a");

    if(a>b)
        printf("b");

    return  0;
}

使用-O3进行编译。这是反汇编:

    pushq   %rbp
Ltmp2:
    .cfi_def_cfa_offset 16
Ltmp3:
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
Ltmp4:
    .cfi_def_cfa_register %rbp
    subq    $16, %rsp
    movl    -4(%rbp), %eax
    subl    -8(%rbp), %eax
    testl   %eax, %eax
    jle LBB0_2
## BB#1:
    movl    $97, %edi
    callq   _putchar
LBB0_2:
    movl    -4(%rbp), %eax
    cmpl    -8(%rbp), %eax
    jle LBB0_4
## BB#3:
    movl    $98, %edi
    callq   _putchar
LBB0_4:
    xorl    %eax, %eax
    addq    $16, %rsp
    popq    %rbp
    ret

-O3a-b>0仍在使用一条额外的指令。

即使您使用ARM编译器编译它,也会有一条额外的指令:

    push    {lr}
    sub sp, sp, #12
    ldr r2, [sp, #0]
    ldr r3, [sp, #4]
    subs    r3, r2, r3
    cmp r3, #0
    ble .L2
    movs    r0, #97
    bl  putchar(PLT)
.L2:
    ldr r2, [sp, #0]
    ldr r3, [sp, #4]
    cmp r2, r3
    ble .L3
    movs    r0, #98
    bl  putchar(PLT)
.L3:
    movs    r0, #0
    add sp, sp, #12
    pop {pc}

请注意,(1)volatile是不切实际的,除非您正在处理例如硬件寄存器或线程共享内存,以及(2)实践中的差异甚至无法衡量。

因为在某些情况下两者具有不同的语义,写出正确的。以后担心优化!

答案 1 :(得分:1)

如果你真的想知道,在C中,假设我们有test.c

int main()
{
  int a = 1000, b = 2000;
  if (a > b) {
    int c = 2;
  }
  if (a - b > 0) {
    int c = 3;
  }
}

gcc -S -O0 test.c汇编,我们得到test.s

.file   "test.c"
.text
.globl  main
.type   main, @function
main:

.LFB0:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movl    $1000, -16(%rbp)
    movl    $2000, -12(%rbp)
    movl    -16(%rbp), %eax
    cmpl    -12(%rbp), %eax
    jle .L2
    movl    $2, -8(%rbp)
.L2:
    movl    -12(%rbp), %eax
    movl    -16(%rbp), %edx
    subl    %eax, %edx
    movl    %edx, %eax
    testl   %eax, %eax
    jle .L4
    movl    $3, -4(%rbp)
.L4:
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
    .ident  "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2"
    .section    .note.GNU-stack,"",@progbits

请参阅以上

    movl    $1000, -16(%rbp)
    movl    $2000, -12(%rbp)
    movl    -16(%rbp), %eax
    cmpl    -12(%rbp), %eax
    jle .L2
    movl    $2, -8(%rbp)

    movl    -12(%rbp), %eax
    movl    -16(%rbp), %edx
    subl    %eax, %edx
    movl    %edx, %eax
    testl   %eax, %eax
    jle .L4
    movl    $3, -4(%rbp)

a - b > 0还需要一步。

注意

  1. 以上内容均在Ubuntu 14.04 gcc 4.8上编译,优化已关闭(-O0
  2. 正如@Blastfurnace指出的那样,使用-O2-O3,汇编代码不再可读。你需要描述一下以获得一个想法。但我相信它们将针对相同的代码进行优化。
  3. 谁在乎

答案 2 :(得分:1)

如果进行减法并测试符号与比较结果相同且运行速度更快,则处理器设计人员会将整数比较指令映射到减法和测试。

我认为您可以假设比较至少与减法和测试一样快,并且具有更清晰的真正主要优势。

答案 3 :(得分:0)

为了便于阅读,我总是选择a > b