C语言 如何使用位运算符,掩码,来确定一个数字是否是另一个数字的倍数?

vatpfxk5  于 2023-03-29  发布在  其他
关注(0)|答案(3)|浏览(246)

所以有人告诉我,这是可以做到的,按位运算和掩码可能非常有用,但我必须在它们的工作方式中遗漏一些东西。
我试图计算一个数字,比如x,是否是y的倍数。如果x是y的倍数,故事就结束了,否则我想增加x,以达到最接近的y的倍数大于x(这样所有的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的倍数?也有人能给予上面给出的代码一个数字解释吗?展示这一点可能会帮助我理解为什么它不起作用。一旦我理解为什么它不起作用,我将能够自己解决问题,我相信。

cclgggtu

cclgggtu1#

我不知道为什么你甚至会考虑使用按位操作来实现这个功能?它们当然有自己的位置,但不是这样。
一个更好的方法是简单地使用如下代码:

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

但要回答你的附加问题,即如何计算一个数字是否是16的倍数,这可以相对容易地完成。你会注意到下面所有倍数的一个模式:

0 == 0000 0000 0000 0000
 16 == 0000 0000 0001 0000
 32 == 0000 0000 0010 0000
 48 == 0000 0000 0011 0000
 64 == 0000 0000 0100 0000
 :
512 == 0000 0010 0000 0000
                      \__/
                       \
                        These bits are always zero.

所以十六的倍数可以用表达式来检测:

(value & 0x0f) == 0

然而,这只适用于2的幂,而不是任意除数。

nxowjjhe

nxowjjhe2#

在平凡的情况下,每个是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中,这些例程是按位完成的。可能想查一本数字逻辑设计的书来获得更多的想法。

sbtkgmzw

sbtkgmzw3#

好了,我已经发现了我的代码中的错误,因为大多数人都说不可能使用掩码来计算一个数字是否是另一个数字的倍数,我想我会分享我学到的东西。这是可能的!-如果你使用正确的数据类型。
如果y被声明为常量unsigned long,那么上面给出的代码就可以工作,因为传入的x也是unsigned long。关键点不是long或常量部分,而是数字是无符号的。这个符号位会导致错误计算,因为数字的第一个位置表示符号,并且当执行按位操作时,符号可能会混淆。
下面是我的代码,如果我们正在寻找16的倍数:const unsigned long y = 16;//在我的例子中全局声明
然后,将一个无符号long传递给运行以下代码的函数:如果(x&(y-1)){ //如果不为0则y的倍数x = x&~(y-1)+ y;} x现在将是16的最接近倍数的大小。

相关问题