Bit manipulation 这个想法背后的位操作代码实现了5/8的一个数?
我正在研究一个问题,我必须使用位运算计算给定数字的八分之五(5/8) 对于正数,我可以很容易地做到。基本上,它是Bit manipulation 这个想法背后的位操作代码实现了5/8的一个数?,bit-manipulation,Bit Manipulation,我正在研究一个问题,我必须使用位运算计算给定数字的八分之五(5/8) 对于正数,我可以很容易地做到。基本上,它是((x>3) 然而,对于负数,它似乎不起作用。我环顾了一下网络,显然,我必须添加一个因子7,然而,我不明白为什么需要这样做?使用向负无穷大方向移动的除法,而普通的C除法则向零方向移动 也就是说,-9/8==1(即,-1.25向零舍入为-1),但-9>-2==2(即,“-1.25”向负无穷大舍入为-2) 为了解决这个问题,对于被8除的特定情况,在负数的情况下,您可以加7来“调整”股息,以
((x>3
)
然而,对于负数,它似乎不起作用。我环顾了一下网络,显然,我必须添加一个因子7,然而,我不明白为什么需要这样做?使用向负无穷大方向移动的除法,而普通的C除法则向零方向移动
也就是说,-9/8==1
(即,-1.25
向零舍入为-1
),但-9>-2==2
(即,“-1.25”向负无穷大舍入为-2)
为了解决这个问题,对于被8除的特定情况,在负数的情况下,您可以加7来“调整”股息,以使四舍五入如您所期望的那样进行
整个问题假设您的C编译器为有符号右移实现了“算术右移”。几乎所有的体系结构/编译器组合都实现了,但标准并不能保证这一点。对于正
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
显然,如果我们计算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
为了让它更直观 以数字为例,-42(不是5的倍数,但无论如何) 将一个基点从右起3处(除以8) 如何四舍五入:将1与所有分数位相加(即如果分数位不全为零,则加法将进入整数部分),因此为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,然后移位。逻辑很复杂,我不太明白,但是如果你只是对x求反呢?
-(-x>3)
,然后重新对结果求反?@dana该逻辑只是x*5/8
,但除法是向下舍入,而不是向上舍入zero@harold你能详细说明为什么需要加7吗?我不能安静地想象它。你能指出为什么我们加7而不是其他东西吗?它在数学上有什么帮助?会有所不同t表示不同的分母?当你用移位法除以负数N
时,你可以加N-1
来向零取整。因此8-1==7
。你可以自己做一些例子-尝试-9,-8和-7
来测试“边界”情况。这类似于你如何“取整”在C中使用正规除法,在除数上加上除数-1,你的意思是负无穷大,对吗?一些负号似乎也有disappeared@harold-没错,我的意思是消极的不公平。我加了大约3到4个消极的符号,希望这就是所有的符号!无可否认,我有一个积极的div例子伊森起初意识到它应该是负面的,但转换得很差。
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