zoukankan      html  css  js  c++  java
  • C语言中的位操作(6)可变位宽的符号扩展

     可变位宽的符号扩展:                                                                                                                               

     有时,我们需要扩展数字的符号位,但是我们不知道该数字的总位数,如果用b表示(或者我们可能会使用类似于java这样缺乏位域的语言编程)

    unsigned b; // 表示数x的位数
    int x;      //将这个b位数符号扩展到r位
    int r;      // 保存r位数字
    int const m = 1U << (b - 1); // 如果b固定,中间量可以提前计算
    
    x = x & ((1U << b) - 1);  // (Skip this if bits in x above position b are already zero.)
    r = (x ^ m) - m;

     上面的代码要求4种操作,但是当位宽是常量而不是变量的时候,只需要2种更快的方法,假设高位都已经为0.

    一种不取决于x的高b位为0,稍快但是稳定性较差的方法如下:

    int const m = CHAR_BIT * sizeof(x) - b;
    r = (x << m) >> m;

    采用3步操作可变位宽的符号扩展:                                                                                                                                                                                     

     以下的代码在某些机器上面可能会比较慢,取决于乘法与除法的,这种版本采用4步操作,如果你知道初始位宽:b,并且b>1 

    你可以采用 r = (x * multipliers[b]) / multipliers[b],只用3步操作使用 来进行符号位扩展。

    unsigned b; // b代表x的位数
    int x;      // 将要转换为r的b位数x
    int r;      //保存为结果r
    #define M(B) (1U << ((sizeof(x) * CHAR_BIT) - B)) 
    // CHAR_BIT=bits/byte
    static int const multipliers[] = 
    {
      0,     M(1),  M(2),  M(3),  M(4),  M(5),  M(6),  M(7),
      M(8),  M(9),  M(10), M(11), M(12), M(13), M(14), M(15),
      M(16), M(17), M(18), M(19), M(20), M(21), M(22), M(23),
      M(24), M(25), M(26), M(27), M(28), M(29), M(30), M(31),
      M(32)
    }; //如果是64位系统,则相应增加
    static int const divisors[] = 
    {
      1,    ~M(1),  M(2),  M(3),  M(4),  M(5),  M(6),  M(7),
      M(8),  M(9),  M(10), M(11), M(12), M(13), M(14), M(15),
      M(16), M(17), M(18), M(19), M(20), M(21), M(22), M(23),
      M(24), M(25), M(26), M(27), M(28), M(29), M(30), M(31),
      M(32)
    };//如果是64位系统,则相应增加
    #undef M
    r = (x * multipliers[b]) / divisors[b];

    下面一种与之不同的非轻便方法,但是需要算术右移来维持符号位,它应该更快。

    const int s = -b; // 或者:  sizeof(x) * CHAR_BIT - b;
    r = (x << s) >> s;
  • 相关阅读:
    工学A B 刊物
    学习OpenCV
    MFC1
    csmath
    走进心理学
    第八篇: UpdateProgress 控件显示正在处理中的信息
    第十篇: Timer 控件
    第六篇: UpdatePanel 控件UpdateMode属性
    第九篇: UpdateProgress 控件用户中断
    第五篇: UpdatePanel 控件RegisterAsyncPostBackControl方法
  • 原文地址:https://www.cnblogs.com/xueda120/p/3068212.html
Copyright © 2011-2022 走看看