我的部门怎么了?

时间:2013-06-07 01:04:11

标签: math division short integer-division

我在-32768和32767之间有一个16位样本。 为了节省空间,我想将其转换为8位样本,因此我将样本除以256,并添加128.

-32768 / 256 = -128 + 128 = 0
32767 / 256 = 127.99 + 128 = 255.99

现在,0将完全适合一个字节,但255.99必须向下舍入到255,导致我的精度松散,因为转换回来时我将得到32512而不是32767。

如何在不丢失原始最小/最大值的情况下执行此操作?我知道我犯了一个非常明显的思想错误,但我无法弄清楚错误所在。

是的,当然我完全清楚我通过划分失去了精度,并且无法从8位样本中推导出原始值,但我只是想知道为什么我没有得到原始最大值。 / p>

3 个答案:

答案 0 :(得分:1)

已经提供了下采样的答案。

这个答案涉及使用全范围的上采样。这是一个C99代码段,演示如何在整个值范围内传播错误:

#include <stdio.h>

int main(void)
{
    for( int i = 0; i < 256; i++ ) {
        unsigned short scaledVal = ((unsigned short)i << 8) + (unsigned short)i;
        printf( "%8d%8hu\n", i, scaledVal );
    }
    return 0;
}

这很简单。您将值左移8,然后再添加原始值。这意味着[0,255]范围内每增加1对应于[0,65535]范围内增加257。

我想指出,这可能会比你开始时效果更差。例如,如果您对65280(0xff00)进行下采样,则会得到255,但是然后进行上采样会得到65535(0xffff),这是总错误255.在数据范围的大部分高端,您将遇到类似的大错误。

你可能会更好地放弃回到[0,65535]范围的概念,而是将你的值减半。也就是说,向左移动并添加127.这意味着错误是均匀的而不是倾斜的。因为您实际上并不知道原始值是什么,所以您可以做的最好的事情是使用正中值来估计它。

总而言之,我认为这在数学上更正确:

unsigned short scaledVal = ((unsigned short)i << 8) + 127;

答案 1 :(得分:0)

您没有获得原始最大值,因为您不能将数字256表示为8位无符号整数。

答案 2 :(得分:0)

如果您尝试将16位整数值压缩为8位整数值范围,则取最重要的8位并保留它们,同时丢弃最低8位。通常,这是通过移位来完成的。 >>运算符是从最高位到最低位的转换,如果使用8次或>>8则可以工作。您也可以屏蔽掉字节并在分割之前将00舍入为舍入,例如8BitInt =(16BitInt&amp; 65280)/ 256; [65280 a.k.a 0xFF00]

你从一个值偏移的每一位都将它减半,比如除以2,然后向下舍入。

由于您正在处理有符号整数,所以上述所有内容都很复杂。

最后我并非100%肯定我在这里得到了一切,因为我真的没有尝试过这样做。