【问题标题】:Do bitwise operators (other than shifts) make any mathematical sense in base-10?按位运算符(除了移位)在 base-10 中是否具有任何数学意义?
【发布时间】:2010-07-23 15:59:20
【问题描述】:

根据wiki shifts 可用于计算 2 的幂:

算术左移 n 是 相当于乘以 2^n (前提是该值不 溢出),而正确的算术 将二进制补码值移位 n 相当于除以 2^n 和 向负无穷舍入。

我一直想知道是否有任何其他位运算符(~,|,&,^)在应用于 base-10 时具有任何数学意义?我了解它们是如何工作的,但是这些运算的结果可以用来计算十进制世界中有用的东西吗?

【问题讨论】:

  • 是的。您可以使用按位和 (2^n - 1) 计算 2 (2^n) 的幂的余数。
  • 我认为这个问题的意思是“按位运算符在 base-10 中是否有任何有意义的表示”,但似乎其他人都认为这是关于浮点数的。
  • @BlueRaja 是的 base-10 就是我的意思,也许这个问题措辞不好?
  • @serg 并没有真正回答您的问题,但每当我需要使用十进制快速计算二进制运算符时,我都会使用此站点:bitwiseoperatorcalculator.com

标签: math bit-manipulation


【解决方案1】:
“是的,base-10 就是我的意思”

在这种情况下,是的,它们可以通过多种方式扩展到 base-10,尽管它们不如二进制有用。

一个想法是&| 等与对单个二进制数字进行算术 mod-2 相同。如果ab 是单个二进制数字,那么

a & b = a * b (mod 2) a ^ b = a + b (mod 2) ~a = 1-a (mod 2) 一个 | b = ~(~a & ~b) = 1 - (1-a)*(1-b) (mod 2)

以 10 为底的等价物将是 (再次注意,这些是按数字应用的,而不是整数)

a & b = a * b (mod 10) a ^ b = a + b (mod 10) ~a = 9-a (mod 10) 一个 | b = ~(~a & ~b) = 9 - (9-a)*(9-b) (mod 10)

前三个在设计使用BCD~a9's complement)的电路时很有用,例如非图形计算器,尽管我们只使用*+ 而不是&^ 编写方程式时。第一个显然也用于some old ciphers

【讨论】:

  • 或者您也可以查看 & 作为最小值,|作为最大值和 ~ 再次作为补码。从数学上讲,这给了你一个格子而不是一个环。
【解决方案2】:

在没有临时变量的情况下交换两个整数的一个有趣技巧是使用按位异或:

void swap(int &a, int &b) {
   a = a ^ b;
   b = b ^ a; //b now = a
   a = a ^ b; //knocks out the original a
}

这是可行的,因为 XOR 是可交换的,所以 a ^ b ^ b = a。

【讨论】:

  • 虽然遗憾的是,大多数类型化语言不允许您对非整数进行 XOR。真可惜……否则,它会让你交换任何东西。
  • @SamDufel:实际上它只会交换任何东西的按位表示。任何包含内部指针的结构(即数据结构的一部分指向另一部分,例如在字符串类型的短字符串优化中)都会中断,因为现在指针将指向 other 对象。
  • @SamDufel:我的意思是你声称“它可以让你交换任何东西”是错误的。
  • 我相信你弄错了,但我认为关于什么是“交换”的迂腐论点不会为这个答案增加价值。
  • @Rich 这仅回答do results of such operations can be used to calculate anything useful in decimal world? 部分问题,应明确提及。
【解决方案3】:

是的,还有其他有用的运算,但它们往往面向涉及 2 次方的运算(出于显而易见的原因),例如测试奇数/偶数、测试 2 的幂、向上/向下舍入到最接近的 2 幂等。

参见 Henry S. Warren 的 Hacker's Delight

【讨论】:

    【解决方案4】:

    在我使用过的每一种语言中(诚然,几乎完全是 C 和 C 衍生语言),按位运算符都是整数运算(当然,除非您覆盖该运算)。

    虽然您可以旋转十进制数的位(毕竟它们有自己的位),但它不一定会得到与旋转整数位相同的结果。请参阅Single PrecisionDouble Precision 以了解十进制数字中的位描述。请参阅Fast Inverse Square Root 以了解位旋转十进制数的有利用法示例。

    编辑

    对于整数,按位运算总是有意义的。位运算是为整数设计的。

    n << 1 == n * 2
    n << 2 == n * 4
    n << 3 == n * 8
    
    n >> 1 == n / 2
    n >> 2 == n / 4
    n >> 3 == n / 8
    
    n & 1 == {0, 1}       // Set containing 0 and 1
    n & 2 == {0, 2}       // Set containing 0 and 2
    n & 3 == {0, 1, 2, 3} // Set containing 0, 1, 2, and 3
    
    n | 1 == {1, n, n+1}
    n | 2 == {2, n, n+2}
    n | 3 == {3, n, n+1, n+2, n+3}
    

    等等。

    【讨论】:

    • 我认为您将术语 decimalfloating point 混淆了——它们不是一回事——例如整数可以是十进制的。
    • 你提出了一个有趣的观点。实际上,撕开float 的部分比int 的部分要好得多。
    • @Paul R:我认为 serg 是在谈论非整数,因为虽然您可以在许多语言中输入十进制、十六进制、八进制或二进制的整数,但二进制表示是相同的,并且它们仍然是整数。 (如果您在没有任何特殊考虑的情况下输出该值,大多数语言将使用十进制,而不管您为输入编写了什么内容)。 0b11001000 = 0310 = 200 = 0xC8
    • @Brian:是的,我想这个问题有点模棱两可。通常,如果人们在谈论整数以外的数字类型时会说“浮点”(或“定点”或其他)。
    • 那么是的,按位运算总是有意义的。位运算是为整数设计的,与基数无关。 n &lt;&lt; 1 == n * 2 表示整数 n
    【解决方案5】:

    【讨论】:

      【解决方案6】:

      您有时可以用按位运算代替布尔运算。例如以下代码:

      如果 ((a

      在 C 中,这可以替换为:

      如果 ((a & b)

      这是因为整数中的一位用作符号位(1 表示负数)。 and 操作 (a & b) 将是一个无意义的数字,但它的符号将是数字符号的按位和,因此检查结果的符号将起作用。

      这可能会或可能不会提高性能。在许多架构和编译器上,做两个布尔测试/分支会更糟。即使使用正常的语法,现代 x86 编译器也可能使用一些较新的指令生成单个分支。

      与往常一样,如果它确实会提高性能...评论代码 - 即将“正常”的做法放在评论中,并说它等效但更快。

      同样,~ |和 ^ 可以以类似的方式使用,所有条件都是 (x 如果 ((a

      变成:

      如果 (((a-b) | (b-c))

      因为只有当 a 小于 b 时 a-b 才会是负数。如果您在最大 int 的 2 倍范围内,则可能会出现问题 - 即算术溢出,所以要小心。

      这些在某些情况下是有效的优化,但在其他情况下完全没用。为了变得非常丑陋,浮点数也有符号位...... ;-)

      示例: 例如,假设您想根据 a、b、c 的顺序采取行动。你可以做一些嵌套的 if/else 结构,或者你可以这样做:

      x = ((a

      我在代码中使用了最多 9 个条件,并且还使用了上面提到的减法和额外的逻辑来隔离符号位而不是小于。它比等效的分支更快。但是,您不再需要进行减法和符号位提取,因为该标准很久以前就已更新为将 true 指定为 1,并且通过条件移动等,现在实际的小于可以非常有效。

      【讨论】:

        猜你喜欢
        • 2012-09-27
        • 1970-01-01
        • 1970-01-01
        • 2015-09-23
        • 1970-01-01
        • 1970-01-01
        • 2010-10-02
        • 2012-11-12
        • 1970-01-01
        相关资源
        最近更新 更多