ape entropy中rice编码用到的正数转负数问题

来源:互联网 发布:js字符串split 编辑:程序博客网 时间:2024/05/29 19:03

在函数 ape_decode_value_3990 中有这么一段代码 ((x >> 1) ^ ((x & 1) - 1)) + 1;   注释是说转成有符号数。


rice编码是对非负数做编码的,因此,在编码前需要把负数转成正数,ape中的转换规则为:


从有符号数y到无符号数x的转换

x =   2y - 1            if y > 0

x = 2 abs(y)= -2y  if y <= 0


示例:

y01-12-23-34-45-56-67-78-89-9x0123456789101112131415161718

即偶数用来表示负数,奇数用来表示正数。


说明:

1)   正数时(最后一个bit是1),表示的实际值是去掉最后一位(符号位),剩下的部分加1.

     例如    101 (二级制),表示的  3这个正数,运算过程就是 101 >> 1  + 1( 101右移一位后加1).

   2)   负数时(最后一个bit是0),去掉最后一位就是实际值(再加上符号)


从无符号数x到有符号数y的转换

y =  (x+1) / 2  如果y表示一个正数

y = -x/2  如果y表示一个非正数


按照如上公式编写c代码可以是如下:


y = (x&1)?(x+1)>>1:((~x)+1)>>1

     其中(~x)+1表示对y取相反数(规则是按位取反后再加一)

In the APE formal reference code, using the formula:  (nValue & 1) ? (nValue >> 1) + 1 : -(nValue >> 1).   Is equal to the above one.

而ffmpeg的参考代码中用的公式是  :
 y=((x >> 1) ^ ((x & 1) - 1)) + 1

不太直接,可能是鲁棒性更好(可移植性更好?)


对这个不太直接的公式的一些补充说明

      异或:与0异或,相当于不变,与1异或,相当于取反。((x >> 1) ^ ((x & 1) - 1)),如果是负数(最后一位是0),则是与全1做异或,相当于按位取反,再加1.  变成计算机中用的补码形式的负数;如果是正数(最后一位是1),则是与全0做异或,相当于不变,再加上1,变成计算机中用的正数。


那么  (x +1)>>1  得到是绝对值。例如  x = 101 (二级制),变成补码是011,表示十进制的3.  那么 ( x + 1 ) >> 1 就是 3(十进制);x=110(二级制,实际值为-3),则 ( x +1 ) >> 1就是3(十进制).




补充:

下面一段英文摘抄自维基百科(略微与上面描述不同,最后一个bit是0来表示正数 1表示负数,刚好与ape相反):

Use with signed integers

Golomb's scheme was designed to encode sequences of non-negative numbers. However it is easily extended to accept sequences containing negative numbersusing an overlap and interleave scheme, in which all values are reassigned to some positive number in a unique and reversible way. The sequence begins: 0, -1, 1, -2, 2, -3, 3, -4, 4 ... The nth negative value (i.e., -n) is mapped to the nth odd number (2n-1), and the mth positive value is mapped to the mth even number (2m). This may be expressed mathematically as follows: apositive value {\displaystyle x}x is mapped to ({\displaystyle x^{\prime }=2|x|=2x,x\geq 0}x^{\prime }=2|x|=2x,x\geq 0), and a negative value {\displaystyle y}y is mapped to ({\displaystyle y^{\prime }=2|y|-1=-2y-1,y<0}y^{\prime }=2|y|-1=-2y-1,y<0). This is an optimal prefix code only if both the positive and the magnitude of the negative values follow a geometric distribution with the same parameter.




x01-12-23-34-45-56-67-78-89-9y0123456789101112131415161718
0 0