加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – x / 2和x >> 1或x * 2和x << 1的差值

发布时间:2020-12-16 06:46:09 所属栏目:百科 来源:网络整理
导读:正如我们所知的计算整数x / 2,我们只写writey = x / 2;类似于x * 2;但优秀的程序员使用位操作来计算它. 他们只做y = x 1; 这两种方法有什么区别吗? 差异,我的意思是所需的时间/空间/内存的差异或两者完全相同(即x 2由x 1实现)? 也是以相同的方式实现与其他
正如我们所知的计算整数x / 2,我们只写writey = x / 2;类似于x * 2;但优秀的程序员使用位操作来计算它.

他们只做y = x>> 1;

这两种方法有什么区别吗?
差异,我的意思是所需的时间/空间/内存的差异或两者完全相同(即x> 2由x>>> 1实现)?

也是以相同的方式实现与其他数字的乘法/除法而不是2(即5 * 5 = 10 * 2 5 * 1 = 10 <1 5 = 25)?

解决方法

这个问题已经在ridiculousfishblog上得到了回答: http://ridiculousfish.com/blog/posts/will-it-optimize.html

  1. Division by 2 to right shift

Will GCC transform an integer division by 2 to a right shift?

int halve_it(int x) {
   return x / 2;
}

int halve_it(int x) {
   return x >> 1;
}

The right shift operator is equivalent to division that rounds towards
negative infinity,but normal division rounds towards zero. Thus the
proposed optimization will produce the wrong result for odd negative
numbers.

The result can be “fixed up” by adding the most significant bit to the
numerator before shifting,and gcc does this.

优秀的程序员让编译器优化他们的代码,除非他们遇到性能损失.

编辑:既然你要求官方消息来源,让我们引用C99的标准理由文件.你在这里找到它:http://www.open-std.org/jtc1/sc22/wg14/www/docs/C99RationaleV5.10.pdf

In C89,division of integers involving negative operands could round upward or downward in an implementation-defined manner; the intent was to avoid incurring overhead in run-time code to check for special cases and enforce specific behavior. In Fortran,however,the result will always truncate toward zero,and the overhead seems to be acceptable to the numeric programming community. Therefore,C99 now requires similar behavior,which should facilitate porting of code from Fortran to C. The table in §7.20.6.2 of this document illustrates the required semantics.

你的优化在C89中是正确的,因为它让编译器按照自己的意愿去做.但是,C99引入了一个符合Fortran代码的新约定.以下是除法运算符的预期示例(始终来自同一文档):

不幸的是,您的优化不符合C99标准,因为它没有给出x = -1的正确结果:

#include <stdio.h>

int div8(int x)
{
    return x/3;
}

int rs8( int x )
{
    return x >> 3;
}

int main(int argc,char *argv[])
{
    volatile int x = -1;
    printf("div : %d n",div8(x) );
    printf("rs : %d n",rs8(x) );

    return 0;
}

Result:
div : 0 
rs : -1 
[Finished in 0.2s]

如果查看已编译的代码,可以发现一个有趣的区别(使用g v4.6.2编译):

0040138c <__Z4div8i>:
  40138c:   55                      push   %ebp
  40138d:   89 e5                   mov    %esp,%ebp
  40138f:   8b 45 08                mov    0x8(%ebp),%eax
  401392:   85 c0                   test   %eax,%eax
  401394:   79 03                   jns    401399 <__Z4div8i+0xd>
  401396:   83 c0 0f                add    $0x7,%eax
  401399:   c1 f8 04                sar    $0x3,%eax
  40139c:   5d                      pop    %ebp
  40139d:   c3                      ret    

0040139e <__Z3rs8i>:
  40139e:   55                      push   %ebp
  40139f:   89 e5                   mov    %esp,%ebp
  4013a1:   8b 45 08                mov    0x8(%ebp),%eax
  4013a4:   c1 f8 03                sar    $0x3,%eax
  4013a7:   5d                      pop    %ebp
  4013a8:   c3                      ret

在第401392行,有一个测试指令,它将检查奇偶校验位,如果数字为负,则将加1 <<<右移3个单位之前(n-1)= 7到x.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读