【问题标题】:How do you use bitwise operators, masks, to find if a number is a multiple of another number?如何使用位运算符、掩码来查找一个数字是否是另一个数字的倍数?
【发布时间】:2015-03-24 03:40:44
【问题描述】:

所以有人告诉我,这是可以做到的,并且按位运算和掩码可能非常有用,但我肯定遗漏了它们的工作原理。

我试图计算一个数字,比如 x,是否是 y 的倍数。如果 x 是 y 的倍数,那么我想增加 x 以达到大于 x 的最接近的 y 倍数(以便所有 x 都适合结果)。我刚开始学习 C,但在理解其中一些任务时遇到了困难。

这是我尝试过的,但是当我输入 5、9 或 24 等数字时,我分别得到以下结果:0、4、4。

    if(x&(y-1)){ //if not 0 then multiple of y
        x = x&~(y-1) + y;
    }

非常感谢任何解释,幕后发生的数学示例。

编辑:所以澄清一下,我有点理解位的移位来确定一个项目是否是一个倍数。 (正如在回复中解释的那样,10100 是 101 的倍数,因为它刚刚被转移)。如果我有数字 16,即 10000,它的补码是 01111。我将如何使用这个补码来查看一个项目是否是 16 的倍数?也有人可以对上面给出的代码进行数字解释吗?展示这一点可能有助于我理解为什么它不起作用。一旦我了解它为什么不起作用,我相信我将能够自己解决问题。

【问题讨论】:

  • 要做到这一点,您别无选择,只能找到除法的其余部分。位运算符不能直接检查余数。但是,您可以仅使用按位运算符进行除法。但是你的问题应该是“如何只用按位运算符进行除法?”在这个网站上被问了很多次
  • 我被要求在实验室中使用这种方法,当时我不明白,现在我正在寻找决赛,需要在那之前了解它。上面给出的代码类似于我的导师刚刚概括的代码。我之前已经找到了使用 mod (余数)的倍数,但这不是我要求的方法。我还被特别要求使用掩码设置为 y-1 的补码的掩码。
  • 什么?!让我们尝试一个简单的,加法,首先:0x1^0x1,哦等一下,没有进位,哦

标签: c bit-manipulation bitmask tilde


【解决方案1】:

你为什么会考虑为此使用按位运算?他们当然有自己的位置,但不是这样。

更好的方法是简单地使用类似的东西:

unsigned multGreaterOrEqual(unsigned x, unsigned y) {
    if ((x % y) == 0)
        return x;
    return (x / y + 1) * y;
}

【讨论】:

  • 虽然我同意按位运算不是生产代码的明显选择,但我猜它是某种编程任务,是课堂或工作场所的旁白(为了好玩),或者某种面试问题的范围超出了预期。
  • 是的,这是在实验室中展示的,然后是作业。
【解决方案2】:

在一般情况下,每个是 2 的幂的偶数倍的数字都会向左移动(这在可能改变符号位时不适用)

例如

10100

是4倍

101

和 10100

是2次

1010

至于其他倍数,则必须通过组合两个班次的输出来找到它们。您可能想查找一些原始的计算机除法方法,其中除法大致类似于

x = a / b

实现方式

buffer = a
while a is bigger than b; do
  yes: subtract a from b
       add 1 to x
done

更快的例程首先尝试找出更高级别的位置值,跳过大量减法。所有这些例程都可以按位完成;但这是一个很大的痛苦。在 ALU 中,这些例程是按位完成的。可能想查找数字逻辑设计书籍以获取更多想法。

【讨论】:

  • 为什么MMU需要按位运算进行除法?那不应该在 ALU 中完成吗?
  • 啊,是的,在 ALU 中。我的错,这里已经很晚了。
  • 这是一个很好的提醒,谢谢。我从测试中意识到,可能是我的数据类型导致了其他问题,而不是我的掩码函数,因为我尝试使用模块来实现它,这是更可接受的执行方式,但我仍然得到不同的数字。
【解决方案3】:

好的,所以我发现了我的代码中的错误,并且由于大多数人说不可能使用掩码计算一个数字是否是另一个数字的倍数,所以我想我会分享我所学到的。 有可能的! - 如果您使用的是正确的数据类型。

如果 y 被声明为一个常量 unsigned long 并且传入的 x 也是一个 unsigned long ,那么上面给出的代码就可以工作。关键不是长或常数部分,而是数字是无符号的。这个符号位会导致计算错误,因为数字中的第一位表示符号,执行按位运算时,符号可能会混淆。

如果我们要查找 16 的倍数,这是我的代码: 常量无符号长 y = 16; //在我的情况下全局声明

然后将一个 unsigned long 传递给运行以下代码的函数: if(x&(y-1)){ //如果不是 0 则为 y 的倍数 x = x&~(y-1) + y; } x 现在将是 16 的最接近倍数的大小。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-01-06
    • 1970-01-01
    • 2010-10-19
    • 1970-01-01
    • 2019-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多