除以2的四舍五入

2024-04-27 09:31:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我在实现教科书上的量化算法。我在一个点上的事情几乎是工作,除了我得到一个错误时,四舍五入。这就是教科书上所说的:

Rounded division by 2^p may be carried out by adding an offset and right-shifting by p bit positions

现在,我知道了正确的转变,但是他们说的是什么补偿?在

下面是我的示例代码:

def scale(x, power2=16):
    if x < 0:
        return -((-x) >> power2)
    else:
        return x >> power2
def main():
    inp = [ 12595827, -330706, 196605, -387168, -274244, 377496, -241980, 
            -545272,  -196605, 24198,   196605,  193584, 104858, 424683,
            -40330,     41944 ]
    expect = [ 192, -5, 3, -6, -4, 5, -3, -8, -3, 0, 3, 3, 1, 6, 0, 0 ]
    actual = map(scale, inp)
    for i in range(len(expect)):
        if actual[i] == expect[i]:
            continue
        print 'inp: % 8d expected: % 3d actual: % 3d err: %d' % (inp[i], 
                expect[i], actual[i], expect[i] - actual[i])
if __name__ == '__main__':
    main()

我正在检查负输入,因为负整数的位移位似乎与实现有关。在

我的输出:

^{pr2}$

教科书中提到的偏移量是多少?我如何用它来消除这个错误?在


Tags: 算法byreturnifmaindef错误事情
3条回答

移位将被截断。移位是一种二进制运算符。我在这里用方括号表示基数:

196605[10] = 101111111111111111[2]
101111111111111111[2] >> 16[10] = 10[2] = 2[10]

要执行正确的四舍五入,您需要在进行移位之前将除数的一半相加。在

^{pr2}$

正如所怀疑的那样,您的算法实际上并不是四舍五入,而是截断除法。更重要的是你的课本上也有错误。所以即使你修正了你的算法,你也不会得到预期的结果。在

为了确认结果是否存在缺陷,可以尝试使用正确的、基于浮点的舍入除法函数运行代码:

def scale(x, power2=16):
    divider = float(1<<power2)
    result = round(x/divider)
    return result

但我们得到以下错误:

^{pr2}$

通过计算舍入除法的正确结果,我们可以确认这些期望实际上是错误的:

377496 / 65536 = 5,7601 -> should round to 6
104858 / 65536 = 1,600 -> should round to 2
-241980 / 65536 = -3,692 -> should round to -4
104858 / 65536 = 1,600 -> should round to 2
-40330 / 65536 = -0,6154 -> should round to -1
41994 / 65536 = 0,641 -> should round to 1

因此,如果四舍五入除法是您真正想要的,那么您的期望值列表应该是:

expect = [ 192, -5, 3, -6, -4, 6, -4, -8, -3, 0, 3, 3, 2, 6, -1, 1 ]

按p移位表示除以2^p向下舍入(截断)。在

如果要除以2^p但四舍五入到最接近的整数,请执行以下操作:

shift-right by (p-1)
add 1
shift-right 1

在您的代码中:

^{pr2}$

相关问题 更多 >