我正在研究一个问题,我必须使用位操作来计算给定数字的五分之八(5/8)吗?
对于正数,我可以很容易地做到。基本上,它是( (x << 2) + x )>> 3
。
然而,对于负数,它似乎不起作用。我环顾网络,显然,我必须增加一个因子7,但是,我不能安静地看看为什么需要这个?
答案 0 :(得分:2)
使用轮向负无穷大进行分割,而正常C分组向零舍入。
也就是说,-9 / 8 == 1
(即-1.25
向零舍入为-1
),但是-9 >> 2 == -2
(即,`-1.25'向负无穷大舍入为 - 2)。
要解决这个问题,对于除以8 的特定情况,您可以在负数的情况下添加7以“调整”被除数,以便按预期进行舍入。
这个问题的全部内容假设您的C编译器为签名的右移实现了“算术右移”。几乎所有的架构/编译器组合都有,但标准并不保证。
答案 1 :(得分:1)
对于正面x
,x >> 3
和x / 8
都朝向零。
对于否定x
,x >> 3
向负无穷大舍入,而x / 8
向零舍入。例子:
-1 >> 3 = -1 -1 / 8 = 0 different
-2 >> 3 = -1 -2 / 8 = 0 different
-3 >> 3 = -1 -3 / 8 = 0 different
-4 >> 3 = -1 -4 / 8 = 0 different
-5 >> 3 = -1 -5 / 8 = 0 different
-6 >> 3 = -1 -6 / 8 = 0 different
-7 >> 3 = -1 -7 / 8 = 0 different
-8 >> 3 = -1 -8 / 8 = -1 same
-9 >> 3 = -2 -9 / 8 = -1 different
-10 >> 3 = -2 -10 / 8 = -1 different
-11 >> 3 = -2 -11 / 8 = -1 different
-12 >> 3 = -2 -12 / 8 = -1 different
-13 >> 3 = -2 -13 / 8 = -1 different
-14 >> 3 = -2 -14 / 8 = -1 different
-15 >> 3 = -2 -15 / 8 = -1 different
-16 >> 3 = -2 -16 / 8 = -2 same
-17 >> 3 = -3 -17 / 8 = -2 different
-18 >> 3 = -3 -18 / 8 = -2 different
-19 >> 3 = -3 -19 / 8 = -2 different
当分子(x
)是分母(8)的倍数时,结果是相同的。对于其他7/8的结果,结果相差1.这意味着如果我们希望>> 3
的行为与/ 8
相同,我们需要更改分子。
一般来说,如果你有一个向下舍入的整数除法运算符,你可以通过在分子中加上(分母-1)来使它向上舍入。但是,让我们按照婴儿步骤到达那里。假设我们通过添加1来改变分子:
( -1 + 1) >> 3 = 0 -1 / 8 = 0 same
( -2 + 1) >> 3 = -1 -2 / 8 = 0 different
( -3 + 1) >> 3 = -1 -3 / 8 = 0 different
( -4 + 1) >> 3 = -1 -4 / 8 = 0 different
( -5 + 1) >> 3 = -1 -5 / 8 = 0 different
( -6 + 1) >> 3 = -1 -6 / 8 = 0 different
( -7 + 1) >> 3 = -1 -7 / 8 = 0 different
( -8 + 1) >> 3 = -1 -8 / 8 = -1 same
( -9 + 1) >> 3 = -1 -9 / 8 = -1 same
(-10 + 1) >> 3 = -2 -10 / 8 = -1 different
(-11 + 1) >> 3 = -2 -11 / 8 = -1 different
(-12 + 1) >> 3 = -2 -12 / 8 = -1 different
(-13 + 1) >> 3 = -2 -13 / 8 = -1 different
(-14 + 1) >> 3 = -2 -14 / 8 = -1 different
(-15 + 1) >> 3 = -2 -15 / 8 = -1 different
(-16 + 1) >> 3 = -2 -16 / 8 = -2 same
(-17 + 1) >> 3 = -2 -17 / 8 = -2 same
(-18 + 1) >> 3 = -3 -18 / 8 = -2 different
(-19 + 1) >> 3 = -3 -19 / 8 = -2 different
现在我们有2/8的结果匹配。尝试添加2:
( -1 + 2) >> 3 = 0 -1 / 8 = 0 same
( -2 + 2) >> 3 = 0 -2 / 8 = 0 same
( -3 + 2) >> 3 = -1 -3 / 8 = 0 different
( -4 + 2) >> 3 = -1 -4 / 8 = 0 different
( -5 + 2) >> 3 = -1 -5 / 8 = 0 different
( -6 + 2) >> 3 = -1 -6 / 8 = 0 different
( -7 + 2) >> 3 = -1 -7 / 8 = 0 different
( -8 + 2) >> 3 = -1 -8 / 8 = -1 same
( -9 + 2) >> 3 = -1 -9 / 8 = -1 same
(-10 + 2) >> 3 = -1 -10 / 8 = -1 same
(-11 + 2) >> 3 = -2 -11 / 8 = -1 different
(-12 + 2) >> 3 = -2 -12 / 8 = -1 different
(-13 + 2) >> 3 = -2 -13 / 8 = -1 different
(-14 + 2) >> 3 = -2 -14 / 8 = -1 different
(-15 + 2) >> 3 = -2 -15 / 8 = -1 different
(-16 + 2) >> 3 = -2 -16 / 8 = -2 same
(-17 + 2) >> 3 = -2 -17 / 8 = -2 same
(-18 + 2) >> 3 = -2 -18 / 8 = -2 same
(-19 + 2) >> 3 = -3 -19 / 8 = -2 different
显然,如果我们计算(x + i) >> 3
,结果的(i + 1)/ 8匹配。因此,为了使所有结果匹配,我们为i求解(i + 1)/ 8 = 1,得到i = 7.如果我们将7加到分子上,这就是我们得到的结果:
( -1 + 7) >> 3 = 0 -1 / 8 = 0 same
( -2 + 7) >> 3 = 0 -2 / 8 = 0 same
( -3 + 7) >> 3 = 0 -3 / 8 = 0 same
( -4 + 7) >> 3 = 0 -4 / 8 = 0 same
( -5 + 7) >> 3 = 0 -5 / 8 = 0 same
( -6 + 7) >> 3 = 0 -6 / 8 = 0 same
( -7 + 7) >> 3 = 0 -7 / 8 = 0 same
( -8 + 7) >> 3 = -1 -8 / 8 = -1 same
( -9 + 7) >> 3 = -1 -9 / 8 = -1 same
(-10 + 7) >> 3 = -1 -10 / 8 = -1 same
(-11 + 7) >> 3 = -1 -11 / 8 = -1 same
(-12 + 7) >> 3 = -1 -12 / 8 = -1 same
(-13 + 7) >> 3 = -1 -13 / 8 = -1 same
(-14 + 7) >> 3 = -1 -14 / 8 = -1 same
(-15 + 7) >> 3 = -1 -15 / 8 = -1 same
(-16 + 7) >> 3 = -2 -16 / 8 = -2 same
(-17 + 7) >> 3 = -2 -17 / 8 = -2 same
(-18 + 7) >> 3 = -2 -18 / 8 = -2 same
(-19 + 7) >> 3 = -2 -19 / 8 = -2 same
答案 2 :(得分:0)
为了让它更具视觉效果,
取数字,比方说,-42(这不是5的倍数,但无论如何)
11010110
将一个小数点放在右边3个位置(这除以8)
11010.110 = -5.25
如何向上舍入:向所有分数位添加1(意味着iff不是全部为零,加法将进入整数部分),所以0.111,然后斩:
11010.110
0.111 = 7/8
--------- +
11011.101 = -4.375
chop:
11011.000 = -5
要转换为普通整数,请移至小数点恰好在最低有效位之前:
11011.000 >>s 3 =
11111011. = still -5, but in normal integer format
在代码中你只是将小数点放在虚拟中(所以什么都不做,但是就好像它在那里一样)并且分数是隐含的(所以7/8写成7)。因为正确的移位无论如何都会抛出这些位,所以斩断是不必要的。剩下的就是加7,然后换班。