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;
  • 相关阅读:
    HAproxy 1.5 dev14 发布
    IBM/DW 使用 Java 测试网络连通性的几种方法
    Skype 4.1 Linux 发布,支持微软帐号登录
    Dorado 7.1.20 发布,Ajax的Web开发平台
    Aspose.Slides for Java 3.0 发布
    开发版本 Wine 1.5.18 发布
    BitNami Rubystack 开始支持 Ruby 2.0
    XWiki 4.3 正式版发布
    Silverlight实例教程 Out of Browser的Debug和Notifications窗口
    Silverlight实例教程 Out of Browser与Office的互操作
  • 原文地址:https://www.cnblogs.com/xueda120/p/3068212.html
Copyright © 2011-2022 走看看