精华内容
下载资源
问答
  • BCD码、十六进制与十进制互转
    千次阅读
    2017-09-07 22:46:26

    在做嵌入式软件的设计中,经常会遇到十六进制、BCD码与十进制之间的转换,最近做M1卡的应用中,涉及了大量的十六进制、BCD码与十进制之间的转换。通过对BCD码、十六进制 权的理解,轻松的实现了他们之间的互换。

    1. #include <stdio.h>
    2. #include <string.h>
    3. /
    4. //
    5. //功能:二进制取反
    6. //
    7. //输入:const unsigned char *src  二进制数据
    8. //      int length                待转换的二进制数据长度
    9. //
    10. //输出:unsigned char *dst        取反后的二进制数据
    11. //
    12. //返回:0    success
    13. //
    14. //
    15. int convert(unsigned char *dst, const unsigned char *src, int length)
    16. {
    17.         int i;
    18.         for(i=0; i<length; i++)
    19.         {
    20.                 dst[i] = src[i]^0xFF;
    21.         }
    22.         return 0;
    23. }
    24. //
    25. //
    26. //功能:十六进制转为十进制
    27. //
    28. //输入:const unsigned char *hex         待转换的十六进制数据
    29. //      int length                       十六进制数据长度
    30. //
    31. //输出:
    32. //
    33. //返回:int  rslt                        转换后的十进制数据
    34. //
    35. //思路:十六进制每个字符位所表示的十进制数的范围是0 ~255,进制为256
    36. //      左移8位(<<8)等价乘以256
    37. //
    38. /
    39. unsigned long HextoDec(const unsigned char *hex, int length)
    40. {
    41.     int i;
    42.     unsigned long rslt = 0;
    43.     for(i=0; i<length; i++)
    44.     {
    45.         rslt += (unsigned long)(hex[i])<<(8*(length-1-i));
    46.                                                         
    47.     }
    48.     return rslt;
    49. }
    50. /
    51. //
    52. //功能:十进制转十六进制
    53. //
    54. //输入:int dec                     待转换的十进制数据
    55. //      int length                  转换后的十六进制数据长度
    56. //
    57. //输出:unsigned char *hex          转换后的十六进制数据
    58. //
    59. //返回:0    success
    60. //
    61. //思路:原理同十六进制转十进制
    62. //
    63. int DectoHex(int dec, unsigned char *hex, int length)
    64. {
    65.     int i;
    66.     for(i=length-1; i>=0; i--)
    67.     {
    68.         hex[i] = (dec%256)&0xFF;
    69.         dec /= 256;
    70.     }
    71.     return 0;
    72. }
    73. /
    74. //
    75. //功能:求权
    76. //
    77. //输入:int base                    进制基数
    78. //      int times                   权级数
    79. //
    80. //输出:
    81. //
    82. //返回:unsigned long               当前数据位的权
    83. //
    84. //
    85. unsigned long power(int base, int times)
    86. {
    87.     int i;
    88.     unsigned long rslt = 1;
    89.     for(i=0; i<times; i++)
    90.         rslt *= base;
    91.     return rslt;
    92. }
    93. /
    94. //
    95. //功能:BCD转10进制
    96. //
    97. //输入:const unsigned char *bcd     待转换的BCD码
    98. //      int length                   BCD码数据长度
    99. //
    100. //输出:
    101. //
    102. //返回:unsigned long               当前数据位的权
    103. //
    104. //思路:压缩BCD码一个字符所表示的十进制数据范围为0 ~ 99,进制为100
    105. //      先求每个字符所表示的十进制值,然后乘以权
    106. //
    107. unsigned long  BCDtoDec(const unsigned char *bcd, int length)
    108. {
    109.      int i, tmp;
    110.      unsigned long dec = 0;
    111.      for(i=0; i<length; i++)
    112.      {
    113.         tmp = ((bcd[i]>>4)&0x0F)*10 + (bcd[i]&0x0F);   
    114.         dec += tmp * power(100, length-1-i);          
    115.      }
    116.      return dec;
    117. }
    118. /
    119. //
    120. //功能:十进制转BCD码
    121. //
    122. //输入:int Dec                      待转换的十进制数据
    123. //      int length                   BCD码数据长度
    124. //
    125. //输出:unsigned char *Bcd           转换后的BCD码
    126. //
    127. //返回:0  success
    128. //
    129. //思路:原理同BCD码转十进制
    130. //
    131. //
    132. int DectoBCD(int Dec, unsigned char *Bcd, int length)
    133. {
    134.      int i;
    135.      int temp;
    136.      for(i=length-1; i>=0; i--)
    137.      {
    138.          temp = Dec%100;
    139.          Bcd[i] = ((temp/10)<<4) + ((temp%10) & 0x0F);
    140.          Dec /= 100;
    141.      }
    142.      return 0;
    143. }
    144. int main()
    145. {
    146.     register int i;
    147.     unsigned char tmp_bff[12] = "";
    148.     //十六进制转十进制
    149.     unsigned char HEX[4] = {0x34, 0xFE, 0x3E, 0xFF};
    150.     unsigned long dec_hex = 0;
    151.     dec_hex = HextoDec(HEX, 4);
    152.     
    153.     printf("dec_hex = %d/n", dec_hex);
    154.     //十进制转十六进制
    155.     DectoHex(dec_hex, tmp_bff, 4);
    156.     for(i=0; i<5; i++)
    157.     {
    158.         printf("tmp_bff[%d] = 0x%02X/n",i, tmp_bff[i]);
    159.     }
    160.     //BCD码转十进制
    161.     unsigned long dec_bcd = 0;
    162.     unsigned char BCD[4] = {0x98, 0x23, 0x45, 0x78};
    163.     dec_bcd = BCDtoDec(BCD, 4);
    164.     printf("dec_bcd = %d/n", dec_bcd);
    165.     //十进制转BCD码
    166.     DectoBCD(dec_bcd, tmp_bff, 4);
    167.     for(i=0; i<5; i++)
    168.     {
    169.         printf("tmp_bff[%d] = 0x%02X/n", i, tmp_bff[i]);
    170.     }
    171.     getchar();
    172. }

    更多相关内容
  • 数据压缩算法—2无损压缩算法

    千次阅读 2018-12-12 20:55:43
      字典算法是最为简单的压缩算法之一。它是把文本中出现频率比较多的单词或词汇组合做成一个对应的字典列表,并用特殊代码来表示这个单词或词汇。例如:   有字典列表:   00=Chinese   01=People   02=...

    几个常见的编码算法

    (一) 字典算法

      字典算法是最为简单的压缩算法之一。它是把文本中出现频率比较多的单词或词汇组合做成一个对应的字典列表,并用特殊代码来表示这个单词或词汇。例如:
      有字典列表:
      00=Chinese
      01=People
      02=China
      源文本:I am a Chinese people,I am from China 压缩后的编码为:I am a 00 01,I am from 02。压缩编码后的长度显著缩小,这样的编码在SLG游戏等专有名词比较多的游戏中比较容易出现,比如《SD高达》。

    (二) 固定位长算法(Fixed Bit Length Packing)

      这种算法是把文本用需要的最少的位来进行压缩编码。
      比如八个十六进制数:1,2,3,4,5,6,7,8。转换为二进制为:00000001,00000010,00000011,00000100,00000101,00000110,00000111,00001000。每个数只用到了低4位,而高4位没有用到(全为0),因此对低4位进行压缩编码后得到:0001,0010,0011,0100,0101,0110,0111,1000。然后补充为字节得到:00010010,00110100,01010110,01111000。所以原来的八个十六进制数缩短了一半,得到4个十六进制数:12,34,56,78。
      这也是比较常见的压缩算法之一。

    (三) RLE算法

      这种压缩编码是一种变长的编码,RLE根据文本不同的具体情况会有不同的压缩编码变体与之相适应,以产生更大的压缩比率。
      变体1:重复次数+字符
    文本字符串:A A A B B B C C C C D D D D,编码后得到:3 A 3 B 4 C 4 D。
      变体2:特殊字符+重复次数+字符
    文本字符串:A A A A A B C C C C B C C C,编码后得到:B B 5 A B B 4 C B B 3 C。编码串的最开始说明特殊字符B,以后B后面跟着的数字就表示出重复的次数。
      变体3:把文本每个字节分组成块,每个字符最多重复 127 次。每个块以一个特殊字节开头。那个特殊字节的第 7 位如果被置位,那么剩下的7位数值就是后面的字符的重复次数。如果第 7 位没有被置位,那么剩下 7 位就是后面没有被压缩的字符的数量。例如:文本字符串:A A A A A B C D E F F F。编码后得到:85 A 4 B C D E 83 F(85H= 10000101B、4H= 00000100B、83H= 10000011B)
      以上3种不RLE变体是最常用的几种,其他还有很多很多变体算法,这些算法在Winzip Winrar这些软件中也是经常用到的。

    (四) LZ77算法

      LZ77算法是由 Lempel-Ziv 在1977发明的,也是GBA内置的压缩算法。LZ77算法有许多派生算法(这里面包括 LZSS算法)。它们的算法原理上基本都相同,无论是哪种派生算法,LZ77算法总会包含一个滑动窗口(Sliding Window)一个前向缓冲器(Read Ahead Buffer)。滑动窗口是个历史缓冲器,它被用来存放输入流的前n个字节的有关信息。一个滑动窗口的数据范围可以从 0K 到 64K,而LZSS算法使用了一个4K的滑动窗口。前向缓冲器是与滑动窗口相对应的,它被用来存放输入流的前n个字节,前向缓冲器的大小通常在0 – 258 之间。这个算法就是基于这些建立的。用下n个字节填充前向缓存器(这里的n是前向缓存器的大小)。在滑动窗口中寻找与前向缓冲器中的最匹配的数据,如果匹配的数据长度大于最小匹配长度 (通常取决于编码器,以及滑动窗口的大小,比如一个4K的滑动窗口,它的最小匹配长度就是2),那么就输出一对**〈长度(length),距离(distance)〉**数组。长度(length)是匹配的数据长度,而距离(distance)说明了在输入流中向后多少字节这个匹配数据可以被找到。
      LZ77压缩算法采用字典的方式进行压缩,是一个简单但十分高效的数据压缩算法。其方式就是把数据中一些可以组织成短语(最长字符)的字符加入字典,然后再有相同字符出现采用标记来代替字典中的短语,如此通过标记代替多数重复出现的方式以进行压缩。LZ77的主要算法逻辑就是,先通过前向缓冲区预读数据,然后再向滑动窗口移入(滑动窗口有一定的长度),不断的寻找能与字典中短语匹配的最长短语,然后通过标记符标记。
      在这里插入图片描述
      目前从前向缓冲区中可以和滑动窗口中可以匹配的最长短语就是(A,B),然后向前移动的时候再次遇到(A,B)的时候采用标记符代替。

    4.1 压缩

      当压缩数据的时候,前向缓冲区与移动窗口之间在做短语匹配的是后会存在2种情况:
      找不到匹配时:将未匹配的符号编码成符号标记(多数都是字符本身)
      找到匹配时:将其最长的匹配编码成短语标记。
      短语标记包含三部分信息:(滑动窗口中的偏移量(从匹配开始的地方计算)、匹配中的符号个数、匹配结束后的前向缓冲区中的第一个符号)。
      一旦把n个符号编码并生成响应的标记,就将这n个符号从滑动窗口的一端移出,并用前向缓冲区中同样数量的符号来代替它们,如此,滑动窗口中始终有最新的短语。通过图来进行解释:
      在这里插入图片描述

    4.2 解压

      解压类似于压缩的逆向过程,通过解码标记和保持滑动窗口中的符号来更新解压数据。
      在这里插入图片描述
      解码字符标记:将标记编码成字符拷贝到滑动窗口中。
      解码短语标记:在滑动窗口中查找响应偏移量,同时找到指定长短的短语进行替换。
      但数组是无法直接用二进制来表示的,LZ77会把编码每八个数分成一组,每组前用一个前缀标示来说明这八个数的属性。比如数据流:A B A C A C B A C A按照LZ77的算法编码为:A B A C<2,2> <4,5>,刚好八个数。按照LZ77的规则,用“0”表示原文输出,“1”表示数组输出。所以这段编码就表示为:00001111B(等于0FH),因此得到完整的压缩编码表示:F A B A C 2 2 4 5。虽然表面上只缩短了1个字节的空间,但当数据流很长的时候就会突出它的优势,这种算法在zip格式中是经常用到。
      

    (五)香农-范诺算法

      将序列分成两部分,使得左部频率总和尽可能接近右部频率总和。
    在这里插入图片描述

    (六)霍夫曼编码(Huffman Encoding)

      香农 - 法诺并不总是产生最优的前缀码:概率{0.35,0.17,0.17,0.16,0.15}是一个将分配非优化代码的Shannon-Fano的编码的一个例子。
      出于这个原因,香农 - 范诺几乎从不使用; 哈夫曼编码几乎是计算简单,生产总是达到预期最低的码字长度的制约下,每个符号是由一个整数组成一个代码代表的前缀码。在大多数情况下,[算术编码]可以产生比哈夫曼或的香农-范诺更大的整体压缩,因为它可以在小数位编码,这更接近实际的符号信息内容。然而,算术编码并没有取代像霍夫曼取代的香农-范诺一样取代哈夫曼,一方面是因为算术编码的计算成本的方式,因为它是由多个专利覆盖。
      在这里插入图片描述
      例如:
      字符串:
        “beep boop beer!”

    字符次数
    ‘b’3
    ‘e’4
    ‘p’2
    ‘ ’2
    ‘o’2
    ‘r’1
    ‘!’1

      然后,我把把这些东西放到Priority Queue中(用出现的次数据当 priority),我们可以看到,Priority Queue 是以Prioirry排序一个数组,如果Priority一样,会使用出现的次序排序。
      接下来把这个Priority Queue 转成二叉树。
      我们始终从queue的头取两个元素来构造一个二叉树(第一个元素是左结点,第二个是右结点),并把这两个元素的priority相加,并放回Priority中(再次注意,这里的Priority就是字符出现的次数)。
      然后,我们再把前两个取出来,形成一个Priority为2+2=4的结点,然后再放回Priority Queue中。继续我们的算法(我们可以看到,这是一种自底向上的建树的过程)。最终我们会得到下面这样一棵二叉树。
      此时,我们把这个树的左支编码为0,右支编码为1,这样我们就可以遍历这棵树得到字符的编码,比如:‘b’的编码是 00,’p’的编码是101, ‘r’的编码是1000。我们可以看到出现频率越多的会越在上层,编码也越短,出现频率越少的就越在下层,编码也越长。
      在这里插入图片描述
      最终我们可以得到下面这张编码表:

    字符霍夫曼编码
    ‘b’00
    ‘e’11
    ‘p’101
    ‘ ’011
    ‘o’010
    ‘r’1000
    ‘!’1001

      这里需要注意一点,当我们encode的时候,我们是按“bit”来encode,decode也是通过bit来完成,比如,如果我们有这样的bitset “1011110111″ 那么其解码后就是 “pepe”。所以,我们需要通过这个二叉树建立我们Huffman编码和解码的字典表。
      这里需要注意的一点是,我们的Huffman对各个字符的编码是不会冲突的,也就是说,不会存在某一个编码是另一个编码的前缀,不然的话就会大问题了。因为encode后的编码是没有分隔符的。
      于是,对于我们的原始字符串 beep boop beer!
      其对就能的二进制为 : 0110 0010 0110 0101 0110 0101 0111 0000 0010 0000 0110 0010 0110 1111 0110 1111 0111 0000 0010 0000 0110 0010 0110 0101 0110 0101 0111 0010 0010 0001
      我们的Huffman的编码为: 0011 1110 1011 0001 0010 1010 1100 1111 1000 1001

    (七)范式霍夫曼编码(Canonical Huffman Code)

    7.1 为什么霍夫曼编码不好,而采用范式霍夫曼编码?
    (1)解码器需要知道哈夫曼编码树的结构,因而编码器必须为解码器保存或传输哈夫曼编码树;
    (2)
    7.2 范式霍夫曼编码要求(1)是前缀编码(2)某一字符编码长度和使用二叉树建立的该字符的编码长度相同。
    7.3 范式霍夫曼编码的步骤
    (1)统计每个要编码符号的频率;
    (2)依据这些频率信息求出,该符号在传统Huffman编码树中的深度,也就是该符号需要的位数、编码长度、码长;
    (3)编码长度由短到长排列,按照以下方式计算范式霍夫曼编码的码:第一位码是按照霍夫曼编码树的码长全设为0,接下里的码是上一个编码+1;
    (4)如果霍夫曼编码树的码长变长,则需要采用 本次编码 = 2*(本次码长-上次码长) * ( 上一个编码 + 1 )得到。
    例如,依据上节的结果,建立范式霍夫曼编码:

    字符霍夫曼编码霍夫曼编码码长范式霍夫曼编码备注
    ‘b’00200按码长全设为0
    ‘e’11201相同码长时,上一码+1
    ‘p’1013100不同码长时,2*(3-2)*(上一码 + 1)
    ‘ ’0113101相同码长时,上一码+1
    ‘o’0103110相同码长时,上一码+1
    ‘r’100041110不同码长时,2*(4-3) *(上一码 + 1)
    ‘!’100141111相同码长时,上一码+1
    (八)算术编码
    8.1 编码原理

    (1)假设有一段数据需要编码,统计里面所有的字符和出现的次数。
    (2)将区间 [0,1) 连续划分成多个子区间,每个子区间代表一个上述字符, 区间的大小正比于这个字符在文中出现的概率 p。概率越大,则区间越大。所有的子区间加起来正好是 [0,1)。
    (3)编码从一个初始区间 [0,1) 开始,设置: low=0,high=1
    (4)不断读入原始数据的字符,找到这个字符所在的区间,比如 [ L, H ),更新:
        low=low+(high−low)∗L
        high=low+(high−low)∗H
    (5)最后将得到的区间 [low, high)中任意一个小数以二进制形式输出即得到编码的数据。

    8.2 例程

      原始数据:ARBER
      计算出现的频率:

    SymbolTimesP
    A10.2
    B10.2
    E10.2
    R20.4

      将这几个字符的区间在 [0,1) 上按照概率大小连续一字排开,我们得到一个划分好的 [0,1)区间:
    在这里插入图片描述
      开始编码,初始区间是 [0,1)。注意这里又用了区间这个词,不过这个区间不同于上面代表各个字符的概率区间 [0,1)。这里我们可以称之为编码区间,这个区间是会变化的,确切来说是不断变小。我们将编码过程用下图完整地表示出来:
    在这里插入图片描述
      拆解开来一步一步看:
      (1)刚开始编码区间是 [0,1),即
        low=0
        high=1
      (2)第一个字符A的概率区间是 [0,0.2),则 L = 0,H = 0.2,更新
        low=low+(high−low)∗L=0
        high=low+(high−low)∗H=0.2
      (3)第二个字符R的概率区间是 [0.6,1),则 L = 0.6,H = 1,更新
        low=low+(high−low)∗L=0.12
        high=low+(high−low)∗H=0.2
      (4)第三个字符B的概率区间是 [0.2,0.4),则 L = 0.2,H = 0.4,更新
        low=low+(high−low)∗L=0.136
        high=low+(high−low)∗H=0.152
      (5)如此以上往复计算。
      上面的图已经非常清楚地展现了算数编码的思想,我们可以看到一个不断变化的小数编码区间。每次编码一个字符,就在现有的编码区间上,按照概率比例取出这个字符对应的子区间。例如一开始A落在0到0.2上,因此编码区间缩小为 [0,0.2),第二个字符是R,则在 [0,0.2)上按比例取出R对应的子区间 [0.12,0.2),以此类推。每次得到的新的区间都能精确无误地确定当前字符,并且保留了之前所有字符的信息,因为新的编码区间永远是在之前的子区间。最后我们会得到一个长长的小数,这个小数即神奇地包含了所有的原始数据,不得不说这真是一种非常精彩的思想。

    8.3 解码

      如果你理解了编码的原理,则解码的方法显而易见,就是编码过程的逆推。从编码得到的小数开始,不断地寻找小数落在了哪个概率区间,就能将原来的字符一个个地找出来。例如得到的小数是0.14432,则第一个字符显然是A,因为它落在了 [0,0.2)上,接下来再看0.14432落在了 [0,0.2)区间的哪一个相对子区间,发现是 [0.6,1), 就能找到第二个字符是R,依此类推。在这里就不赘述解码的具体步骤了。
      编程实现:
      算数编码的原理简洁而又精致,理解起来也不很困难,但具体的编程实现其实并不是想象的那么容易,主要是因为小数的问题。虽然我们在讲解原理时非常容易地不断计算,但如果真的用编程实现,例如C++,并且不借助第三方数学库,我们不可能简单地用一个double类型去表示和计算这个小数,因为数据和编码可以任意长,小数也会到达小数点后成千上万位。
      怎么办?其实也很容易,小数点是可以挪动的。给定一个编码区间,例如从上面例子里最后的区间 [0.14432,0.1456)开始,假定还有新的数据进来要继续编码。现有区间小数点后的高位0.14其实是确定的,那么实际上14已经可以输出了,小数点可以向后移动两位,区间变成 [0.432,0.56),在这个区间上继续计算后面的子区间。这样编码区间永远保持在一个有限的精度要求上。
      上述是基于十进制的,实际数字是用二进制表示的,当然原理是一样的,用十进制只是为了表述方便。算数编码/解码的编程实现其实还有很多tricky的东西和corner case,我当时写的时候debug了好久,因此我也建议读者自己动手写一遍,相信会有收获。

    8.4 算术编码 vs 哈夫曼编码

      这其实是我想重点探讨的一个部分。在这里默认你已经懂哈夫曼编码,因为这是一种最基本的压缩编码,算法课都会讲。哈夫曼编码和算数编码都属于熵编码,仔细分析它们的原理,这两种编码是十分类似的,但也有微妙的不同之处,这也导致算数编码的压缩率通常比哈夫曼编码略高,这些我们都会加以探讨。
      不过我们首先要了解什么是熵编码,熵是借用了物理上的一个概念,简单来说表示的是物质的无序度,混乱度。信息学里的熵表示数据的无序度,熵越高,则包含的信息越多。其实这个概念还是很抽象,举个最简单的例子,假如一段文字全是字母A,则它的熵就是0,因为根本没有任何变化。如果有一半A一半B,则它可以包含的信息就多了,熵也就高。如果有90%的A和10%的B,则熵比刚才的一半A一半B要低,因为大多数字母都是A。
      熵编码就是根据数据中不同字符出现的概率,用不同长度的编码来表示不同字符。出现概率越高的字符,则用越短的编码表示;出现概率地的字符,可以用比较长的编码表示。这种思想在哈夫曼编码中其实已经很清晰地体现出来了。那么给定一段数据,用二进制表示,最少需要多少bit才能编码呢?或者说平均每个字符需要几个bit表示?其实这就是信息熵的概念,如果从数学上理论分析,香农天才地给出了如下公式:
      在这里插入图片描述
      其中 p (xi) 表示每个字符出现的概率。log对数计算的是每一个字符需要多少bit表示,对它们进行概率加权求和,可以理解为是求数学期望值,最后的结果即表示最少平均每个字符需要多少bit表示,即信息熵,它给出了编码率的极限。
      算术编码和哈夫曼编码的比较
      在这里我们不对信息熵和背后的理论做过多分析,只是为了帮助理解算数编码和哈夫曼编码的本质思想。为了比较这两种编码的异同点,我们首先回顾哈夫曼编码,例如给定一段数据,统计里面字符的出现次数,生成哈夫曼树,我们可以得到字符编码集:

    SymbolTimesEncoding
    a300
    b301
    c210
    d1110
    e2111

    在这里插入图片描述
      仔细观察编码所表示的小数,从0.0到0.111,其实就是构成了算数编码中的各个概率区间,并且概率越大,所用的bit数越少,区间则反而越大。如果用哈夫曼编码一段数据abcde,则得到:00 01 10 110 111。
      如果点上小数点,把它也看成一个小数,其实和算数编码的形式很类似,不断地读入字符,找到它应该落在当前区间的哪一个子区间,整个编码过程形成一个不断收拢变小的区间。
      由此我们可以看到这两种编码,或者说熵编码的本质。概率越小的字符,用更多的bit去表示,这反映到概率区间上就是,概率小的字符所对应的区间也小,因此这个区间的上下边际值的差值越小,为了唯一确定当前这个区间,则需要更多的数字去表示它。我们仍以十进制来说明,例如大区间0.2到0.3,我们需要0.2来确定,一位足以表示;但如果是小的区间0.11112到0.11113,则需要0.11112才能确定这个区间,编码时就需要5位才能将这个字符确定。其实编码一个字符需要的bit数就等于 -log ( p ),这里是十进制,所以log应以10为底,在二进制下以2为底,也就是香农公式里的形式。
      哈夫曼编码的不同之处就在于,它所划分出来的子区间并不是严格按照概率的大小等比例划分的。例如上面的d和e,概率其实是不同的,但却得到了相同的子区间大小0.125;再例如c,和d,e构成的子树,c应该比d,e的区间之和要小,但实际上它们是一样的都是0.25。我们可以将哈夫曼编码和算术编码在这个例子里的概率区间做个对比:
      在这里插入图片描述
      这说明哈夫曼编码可以看作是对算数编码的一种近似,它并不是完美地呈现原始数据中字符的概率分布。也正是因为这一点微小的偏差,使得哈夫曼编码的压缩率通常比算数编码略低一些。或者说,算数编码能更逼近香农给出的理论熵值。
      更好地理解,最简单的例子
      比如有一段数据,A出现的概率是0.8,B出现的概率是0.2,现在要编码数据:
      AAA…AAABBB…BBB (800个A,200个B)
      如果用哈夫曼编码,显然A会被编成0,B会被编成1,如果表示在概率区间上,则A是 [0, 0.5),B是 [0.5, 1)。为了编码800个A和200个B,哈夫曼会用到800个0,然后跟200个1:
      0.000…000111…111 (800个0,200个1)
      在编码800个A的过程中,如果我们试图去观察编码区间的变化,它是不断地以0.5进行指数递减,最后形成一个 [0, 0.5^800) 的编码区间,然后开始B的编码。
      但是如果是算术编码呢?因为A的概率是0.8,所以算数编码会使用区间 [0, 0.8) 来编码A,800个A则会形成一个区间 [0, 0.8^800),显然这个区间比 [0, 0.5^800) 大得多,也就是说800个A,哈夫曼编码用了整整800个0,而算数编码只需要不到800个0,更少的bit数就能表示。
      当然对B而言,哈夫曼编码的区间大小是0.5,算数编码是0.2,算数编码会用到更多的bit数,但因为B的出现概率比A小得多,总体而言,算术编码”牺牲“B而“照顾”A,最终平均需要的bit数就会比哈夫曼编码少。而哈夫曼编码,由于其算法的特点,只能“不合理”地使用0.5和0.5的概率分布。这样的结果是,出现概率很高的A,和出现概率低的B使用了相同的编码长度1。两者相比,显然算术编码能更好地实现熵编码的思想。
      从另外一个角度来看,在哈夫曼编码下,整个bit流可以清晰地分割出原始字符串:
      在这里插入图片描述
      而在算术编码下,每一个字符并不是严格地对应整数个bit的,有些字符与字符之间的边界可能是模糊的,或者说是重叠的,所以它的压缩率会略高:
      在这里插入图片描述
      当然这样的解释并不完全严格,如果一定要究其原因,那必须从数学上进行证明,算数编码的区间分割是更接近于信息熵的结果的,这就不在本文的讨论范围了。在这里我只是试图用更直观地方式解释算数编码和哈夫曼编码之间微妙的区别,以及它们同属于熵编码的本质性原理。

    8.5 总结

      算术编码的讲解就到这里。说实话我非常喜欢这种编码以及它所蕴含的思想,那种触及了数学本质的美感。如果说哈夫曼编码只是直观地基于概率,优化了字符编码长度实现压缩,那么算术编码是真正地从信息熵的本质,展现了信息究竟是以怎样的形式进行无损压缩,以及它的极限是什么。在讨论算术编码时,总是要提及哈夫曼编码,并与之进行比较,我们必须认识到它们之间的关系,才能对熵编码有一个完整的理解。
    reference:
    https://segmentfault.com/img/bVWFcv?w=515&h=287
      
      
      
      
      

    展开全文
  • ​ 利用PROTEUS平台,建立8086 的十六进制转BCD例子。 二、实验目的 1、熟悉实验系统的编程和使用。 2、掌握简单的数值转换算法。 3、基本了解数值各种表达方法。 三、实验说明 计算机中的数值有各种表达方式...

    一、实验要求

    ​ 利用PROTEUS平台,建立8086 的十六进制转BCD例子。

    二、实验目的

    1、熟悉实验系统的编程和使用。

    2、掌握简单的数值转换算法。

    3、基本了解数值各种表达方法。

    三、实验说明

    计算机中的数值有各种表达方式,这是计算机的基础。掌握各种数制之间的转换是一种基本功。有兴趣的同学可以试试将BCD转换成十六进制码。

    四、实验程序流程图

    在这里插入图片描述

    五、实验步骤

    a.仿真代码

    ;将AX拆为5个BCD码,并存入RESULT开始的5个单元
    ;AX=0FFFFH=65535
    CODE SEGMENT
         ASSUME CS:CODE, DS:DATA
    START:
         MOV AX, DATA
         MOV DS, AX
         MOV DX,0000H
         MOV AX, 65535	;被转换的数字
         MOV CX, 10000
         DIv CX			; DIV用AX除以CX
         MOV RESULT, AL ; 除以 10000, 得WAN位数,AL中存的是商
         MOV AX,DX      ; DX中存储的是余数
         MOV DX,0000H
         MOV CX, 1000
         DIv CX
         MOV RESULT+1, AL ; 除以 1000, 得QIAN位数
         MOV AX,DX
         MOV DX,0000H
         MOV CX, 100
         DIv CX
         MOV RESULT+2, AL ; 除以 100, 得BAI位数
         MOV AX,DX
         MOV DX,0000H
         MOV CX, 10
         DIv CX
         MOV RESULT+3, AL ; 除以 10, 得SHI位数
         MOV RESULT+4, DL ; 得GE位数
         JMP $
    CODE ENDS
    DATA SEGMENT  
         RESULT Db 5 DUP(?)
    DATA ENDS
         END START
    

    b.调试、验证

    首先AX=65535=FFFFH,CX=10000=2710H

    在这里插入图片描述

    执行完DIV CX后,AX中存储65535/10000的商6,DX存储余数159FH=5535.

    在这里插入图片描述

    然后商6H作为万位结果,存入内存。
    在这里插入图片描述
    将DX内的余数移入AX后,将DX重置为0,再将CX设置为1000=3E8H。
    在这里插入图片描述
    执行完DIV CX后,AX中存储5535/1000的商5,DX存储余数217H=535.

    在这里插入图片描述

    然后商5H作为千位结果,存入内存。
    在这里插入图片描述
    将DX内的余数移入AX后,将DX重置为0,再将CX设置为100=64H。

    在这里插入图片描述

    执行完DIV CX后,AX中存储535/100的商5,DX存储余数23H=35.

    在这里插入图片描述

    然后商5H作为百位结果,存入内存。
    在这里插入图片描述
    将DX内的余数移入AX后,将DX重置为0,再将CX设置为10=AH。

    在这里插入图片描述

    执行完DIV CX后,AX中存储35/10的商3,DX存储余数5H=5.

    在这里插入图片描述

    然后商5H作为十位结果,存入内存。

    在这里插入图片描述

    余数可以直接作为个位结果存入内存。

    在这里插入图片描述

    六. 实验结果和体会

    实验结果如上,可以发现内存中存储了十进制表示的65535.成功实现了十六进制到BCD码的转换。

    然而该程序仍存在不小缺陷,其对各位的处理是定死在程序中的,对于大于一个字节的十六进制就无能为力了。如果转成循环结构,既能应对更长的数据处理,又能节省程序内存。

    七. 扩展题目程序和实验结果

    ;将12345转成16进制,并存入RESULT
    CODE SEGMENT
         ASSUME CS:CODE, DS:DATA
    START:
         MOV AX, DATA
         MOV DS, AX
         MOV DX,0000H
         MOV AX, 12345
         MOV CX, 1000H
         DIv CX
         MOV RESULT, AL ; 除以 1000H, 得QIAN位数
         MOV AX,DX
         MOV DX,0000H
         MOV CX, 100H
         DIv CX
         MOV RESULT+1, AL ; 除以 100H, 得BAI位数
         MOV AX,DX
         MOV DX,0000H
         MOV CX, 10H
         DIv CX
         MOV RESULT+2, AL ; 除以 10H, 得SHI位数
         MOV RESULT+3, DL ; 得GE位数
         JMP $
    CODE ENDS
    DATA SEGMENT  
         RESULT Db 5 DUP(?)
    DATA ENDS
         END START
    
    

    相比原程序,该程序只改动了AX初始化的数值为12345,并将各除数从十进制改为十六进制。并且由于在十六进制下只有四位数,故删去了一次除法。实际上不删的话也只是在最前方多了个0.

    实验未开始时的内存

    [外链图片转存失败(img-Wwc5EqwB-1569060123686)(5-15.PNG)]

    还没初始化时寄存器全为0

    在这里插入图片描述

    程序执行完后,内存多了3039H=12345
    在这里插入图片描述
    而此时的寄存器保存着最后一次除法的结果,39H/10H的商为3H,余数为9H,分别在AX与DX中。CX中存着除数10H。

    展开全文
  • 十进制转成十六进制:Integer.toHexString(int i)十进制转成八进制Integer.toOctalString(int i) 十进制转成二进制Integer.toBinaryString(int i)十六进制转成十进制Integer.valueOf("FFFF",16).toString...
    十进制转成十六进制:
    Integer.toHexString(int i)
    十进制转成八进制
    Integer.toOctalString(int i) 
    十进制转成二进制
    Integer.toBinaryString(int i)
    十六进制转成十进制
    Integer.valueOf("FFFF",16).toString()
    八进制转成十进制
    Integer.valueOf("876",8).toString()
    二进制转十进制
    Integer.valueOf("0101",2).toString()

    有什么方法可以直接将2,8,16进制直接转换为10进制的吗?
    java.lang.Integer类
    parseInt(String s, int radix)
    使用第二个参数指定的基数,将字符串参数解析为有符号的整数。
    examples from jdk:
    parseInt("0", 10) returns 0
    parseInt("473", 10) returns 473
    parseInt("-0", 10) returns 0
    parseInt("-FF", 16) returns -255
    parseInt("1100110", 2) returns 102
    parseInt("2147483647", 10) returns 2147483647
    parseInt("-2147483648", 10) returns -2147483648
    parseInt("2147483648", 10) throws a NumberFormatException
    parseInt("99", 8) throws a NumberFormatException
    parseInt("Kona", 10) throws a NumberFormatException
    parseInt("Kona", 27) returns 411787

    进制转换如何写(二,八,十六)不用算法
    Integer.toBinaryString
    Integer.toOctalString

    Integer.toHexString 

    例一:

    [java]  view plain  copy
    1. public class Test{  
    2.   public static void main(String args[]){  
    3.   
    4.    int i=100;  
    5.    String binStr=Integer.toBinaryString(i);  
    6.    String otcStr=Integer.toOctalString(i);  
    7.    String hexStr=Integer.toHexString(i);  
    8.    System.out.println(binStr);  
    例二:

    [java]  view plain  copy
    1. public class TestStringFormat {  
    2.   public static void main(String[] args) {  
    3.    if (args.length == 0) {  
    4.       System.out.println("usage: java TestStringFormat <a number>");  
    5.       System.exit(0);  
    6.    }  
    7.   
    8.    Integer factor = Integer.valueOf(args[0]);  
    9.   
    10.    String s;  
    11.   
    12.    s = String.format("%d", factor);  
    13.    System.out.println(s);  
    14.    s = String.format("%x", factor);  
    15.    System.out.println(s);  
    16.    s = String.format("%o", factor);  
    17.    System.out.println(s);  
    18.   }  
    19. }  

    BCD(Binary Coded Decimal)是用二进制编码表示的十进制数(见表3.3),十进制数采用0~9十个数字,是人们最常用的。在计算机中,同一个数可以用两种BCD格式来表示:①压缩的BCD码 ②非压缩的BCD码 
      压缩的BCD码:
      压缩的BCD码用4位二进制数表示一个十进制数位,整个十进制数用一串BCD码来表示。例如,十进制数59表示成压缩的BCD码为0101 1001,十进制数1946表示成压缩的BCD码为0001 1001 0100 0110。

      非压缩的BCD码:
      非压缩的BCD码用8位二进制数表示一个十进制数位,其中低4位是BCD码,高4位是0。例如,十进制数78表示成压缩的BCD码为0000 0111 0000 1000。

      从键盘输入数据时,计算机接收的是ASCII码,要将ASCII码表示的数转换成BCD码是很简单的,只要把ASCII码的高4位清零即可。反之,如果要把BCD码转换成ASII码,只要把BCD码"或|"00110000即可。

    Java实现:

    public static void main(String[] args) {
      byte[] bcd = str2cbcd("01234567897658935260");
      for (int i = 0; i < bcd.length; i++) {
       System.out.println(bcd[i]);
      }
      System.out.println(cbcd2string(bcd));
     }

     public static byte[] str2cbcd(String s) {
      if (s.length() % 2 != 0) {
       s = "0" + s;
      }
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      char[] cs = s.toCharArray();
      for (int i = 0; i < cs.length; i += 2) {
       int high = cs[i] - 48;
       int low = cs[i + 1] - 48;
       baos.write(high << 4 | low);
      }
      return baos.toByteArray();
     }

     public static String cbcd2string(byte[] b) {
      StringBuffer sb = new StringBuffer();
      for (int i = 0; i < b.length; i++) {
       int h = ((b[i]&0xff) >> 4) + 48;
       sb.append((char) h);
       int l = (b[i] & 0x0f) + 48;
       sb.append((char) l);
      }
      return sb.toString();

     }


    java二进制,字节数组,字符,十六进制,BCD编码转换2007-06-07 00:17/**
        * 把16进制字符串转换成字节数组
        * 
    @param hex
        * 
    @return
        
    */

    public static byte[] hexStringToByte(String hex) {
        
    int len = (hex.length() / 2);
        
    byte[] result = new byte[len];
        
    char[] achar = hex.toCharArray();
        
    for (int i = 0; i < len; i++{
         
    int pos = i * 2;
         result[i] 
    = (byte) (toByte(achar[pos]) << 4 | toByte(achar[pos + 1]));
        }

        
    return result;
    }


    private static byte toByte(char c) {
        
    byte b = (byte"0123456789ABCDEF".indexOf(c);
        
    return b;
    }


    /**
        * 把字节数组转换成16进制字符串
        * 
    @param bArray
        * 
    @return
        
    */

    public static final String bytesToHexString(byte[] bArray) {
        StringBuffer sb 
    = new StringBuffer(bArray.length);
        String sTemp;
        
    for (int i = 0; i < bArray.length; i++{
         sTemp 
    = Integer.toHexString(0xFF & bArray[i]);
         
    if (sTemp.length() < 2)
          sb.append(
    0);
         sb.append(sTemp.toUpperCase());
        }

        
    return sb.toString();
    }


    /**
        * 把字节数组转换为对象
        * 
    @param bytes
        * 
    @return
        * 
    @throws IOException
        * 
    @throws ClassNotFoundException
        
    */

    public static final Object bytesToObject(byte[] bytes) throws IOException, ClassNotFoundException {
        ByteArrayInputStream in 
    = new ByteArrayInputStream(bytes);
        ObjectInputStream oi 
    = new ObjectInputStream(in);
        Object o 
    = oi.readObject();
        oi.close();
        
    return o;
    }


    /**
        * 把可序列化对象转换成字节数组
        * 
    @param s
        * 
    @return
        * 
    @throws IOException
        
    */

    public static final byte[] objectToBytes(Serializable s) throws IOException {
        ByteArrayOutputStream out 
    = new ByteArrayOutputStream();
        ObjectOutputStream ot 
    = new ObjectOutputStream(out);
        ot.writeObject(s);
        ot.flush();
        ot.close();
        
    return out.toByteArray();
    }


    public static final String objectToHexString(Serializable s) throws IOException{
        
    return bytesToHexString(objectToBytes(s));
    }


    public static final Object hexStringToObject(String hex) throws IOException, ClassNotFoundException{
        
    return bytesToObject(hexStringToByte(hex));
    }


    /**
        * @函数功能: BCD码转为10进制串(阿拉伯数据)
        * @输入参数: BCD码
        * @输出结果: 10进制串
        
    */

    public static String bcd2Str(byte[] bytes){
        StringBuffer temp
    =new StringBuffer(bytes.length*2);

        
    for(int i=0;i<bytes.length;i++){
         temp.append((
    byte)((bytes[i]& 0xf0)>>>4));
         temp.append((
    byte)(bytes[i]& 0x0f));
        }

        
    return temp.toString().substring(0,1).equalsIgnoreCase("0")?temp.toString().substring(1):temp.toString();
    }


    /**
        * @函数功能: 10进制串转为BCD码
        * @输入参数: 10进制串
        * @输出结果: BCD码
        
    */

    public static byte[] str2Bcd(String asc) {
        
    int len = asc.length();
        
    int mod = len % 2;

        
    if (mod != 0{
         asc 
    = "0" + asc;
         len 
    = asc.length();
        }


        
    byte abt[] = new byte[len];
        
    if (len >= 2{
         len 
    = len / 2;
        }


        
    byte bbt[] = new byte[len];
        abt 
    = asc.getBytes();
        
    int j, k;

        
    for (int p = 0; p < asc.length()/2; p++{
         
    if ( (abt[2 * p] >= '0'&& (abt[2 * p] <= '9')) {
          j 
    = abt[2 * p] - '0';
         }
     else if ( (abt[2 * p] >= 'a'&& (abt[2 * p] <= 'z')) {
          j 
    = abt[2 * p] - 'a' + 0x0a;
         }
     else {
          j 
    = abt[2 * p] - 'A' + 0x0a;
         }


         
    if ( (abt[2 * p + 1>= '0'&& (abt[2 * p + 1<= '9')) {
          k 
    = abt[2 * p + 1- '0';
         }
     else if ( (abt[2 * p + 1>= 'a'&& (abt[2 * p + 1<= 'z')) {
          k 
    = abt[2 * p + 1- 'a' + 0x0a;
         }
    else {
          k 
    = abt[2 * p + 1- 'A' + 0x0a;
         }


         
    int a = (j << 4+ k;
         
    byte b = (byte) a;
         bbt[p] 
    = b;
        }

        
    return bbt;
    }

    /**
        * @函数功能: BCD码转ASC码
        * @输入参数: BCD串
        * @输出结果: ASC码
        
    */

    public static String BCD2ASC(byte[] bytes) {
        StringBuffer temp 
    = new StringBuffer(bytes.length * 2);

        
    for (int i = 0; i < bytes.length; i++{
         
    int h = ((bytes[i] & 0xf0>>> 4);
         
    int l = (bytes[i] & 0x0f);   
         temp.append(BToA[h]).append( BToA[l]);
        }

        
    return temp.toString() ;
    }


    /**
        * MD5加密字符串,返回加密后的16进制字符串
        * 
    @param origin
        * 
    @return
        
    */

    public static String MD5EncodeToHex(String origin) 
           
    return bytesToHexString(MD5Encode(origin));
         }


    /**
        * MD5加密字符串,返回加密后的字节数组
        * 
    @param origin
        * 
    @return
        
    */

    public static byte[] MD5Encode(String origin){
        
    return MD5Encode(origin.getBytes());
    }


    /**
        * MD5加密字节数组,返回加密后的字节数组
        * 
    @param bytes
        * 
    @return
        
    */

    public static byte[] MD5Encode(byte[] bytes){
        MessageDigest md
    =null;
        
    try {
         md 
    = MessageDigest.getInstance("MD5");
         
    return md.digest(bytes);
        }
     catch (NoSuchAlgorithmException e) {
         e.printStackTrace();
         
    return new byte[0];
        }

      
    }

    //关于byte:    signed byte 把 0x00 ~ 0xff 映射成范围 0~127和 -128~-1    两段,比较简单的办法用 (b+256)%256的办法令其值回到0~255,或者用&0xff并赋给一个int。参考http://www.jsfsoft.com:8080/beyond-pebble/pinxue/2006/08/23/1156309692525.html 

    展开全文
  • 支持 FAT, NTFS, Ext2/3, ReiserFS, Reiser4, UFS, CDFS, UDF 文件系统 硬盘, 软盘, CD-ROM 和 DVD, ZIP, Smart Media, Compact Flash, 等磁盘编辑器... ...可导入剪贴板所有格式数据, 包括 ASCII、16 进制数据
  • C++实现十六进制字符串转换为十进制整数的方法本文实例讲述了C++实现十六进制字符串转换为十进制整数的方法。分享给大家供大家参考。具体实现方法如下:/** 将十六进制数字组成的字符串(包含可选的前缀0x或0X)转换为...
  • 浅析数据压缩算法

    千次阅读 2017-05-17 15:51:17
    数据压缩是减少信息传输量最经济直接的办法,所以这篇文章将讲解一些经典的数据压缩算法。 一 热身:基因组 对于生物学的基因研究中,A、C、T、G是是用来表示生物DNA的四种碱基,对基因序列的处理实际上是对这四种...
  • 本文以压缩进制数据为例描述了压缩这些数据的实践。 分析案例 在传输的数据中,有各种类型的数据,有字符串、时间、十进制或bool等,本文将分析十进制这种类型。 在.net中,decimal是一个可以描述较大数据和...
  • 几种压缩算法的原理介绍

    千次阅读 2016-01-28 22:00:19
    可惜LZW(LZ78)压缩算法是有版权的,不然可以拿来用用。  下面是几种常见文件压缩算法原理介绍: 字典算法 字典算法是最为简单的压缩算法之一。它是把文本中出现频率比较多的单词或词汇组合做成一个对应的
  • 16进制编辑器

    2015-08-26 19:42:16
     可导入剪贴板所有格式数据, 包括 ASCII、16 进制数据  可进行 2 进制、16 进制 ASCII, Intel 16 进制, 和 Motorola S 转换  字符集: ANSI ASCII, IBM ASCII, EBCDIC, (Unicode)  立即窗口切换、打印、生成随机...
  • 在线十六进制编辑器支持Base64 + LZJB编码的URL,以将数据加载到其中。 这个特定的LZJB生成与HexEd.it期望相同的字节流。 其他的(例如 )则没有。 请注意, Iuppiter.js的Base64实现似乎不兼容,不正确或有故障。...
  • 几个常见的压缩算法(转)

    千次阅读 2013-10-30 21:08:04
    字典算法是最为简单的压缩算法之一。它是把文本中出现频率比较多的单词或词汇组合做成一个对应的字典列表,并用特殊代码来表示这个单词或词汇。例如: 有字典列表: 00=Chinese 01=People 02=China 源文本:I ...
  • 开源最前线(ID:OpenSourceTop) 猿妹整编综合自:https://github.com/WerWolv/ImHex十六进制编辑器,用来以16进制视图进行文本编辑的编辑工具软...
  • TEA(Tiny Encryption Algorithm) 是一种简单高效的加密算法,以加密解密速度快,实现简单著称。算法真的很简单,TEA算法每一次可以操作64-bit(8-byte),采用128-bit(16-byte)作为key,算法采用迭代的形式,推荐的...
  • #include#includeusingnamespacestd;typedefunsignedcharbyte;/*class PngMsg{private :unsigned... //十进制,相当于16进制89.50.4e.47.0d.0a.1a.0a;char widthloc;char heigtMsgloc;char BitDepthloc;//图像深度c...
  • WinHex(16进制编辑器)

    万次阅读 2019-08-07 14:40:10
    WinHex是一款广为人知的16进制文本编辑器,正如开发人员和程序员所知道的,十六进制代码被生成并应用到应用程序代码中,并且彼此之间有着非常深的连接,这样就不会更改任何数据并损坏应用程序。如果用户错误地更改了...
  • 小而巧的数字压缩算法:zigzag

    千次阅读 2017-08-17 22:47:03
    阅读facebook开源的RPC(Remote Procedure Call)框架thrift源代码的时候,本来是在阅读框架,却不小心被zigzag这个钻石般...后来去百度搜索zigzag,却得到满屏图像相关的一个算法(看来起名字得有特点才行)。既然
  • 再学习了haffman算法之后发现压缩算法很有意思,上网查了点资料,这是做好的一篇(主要是我能理解)。前面几种都能看懂,关键是那个LZ77算法。这个是很强大的压缩算法,zip,rar用得都是这种算法,让我们来感叹下两个...
  •  在字符串算法—数据压缩中,我们介绍了哈夫曼压缩算法(Huffman compression),本文将介绍LZW算法。   2. LZW算法  这个算法很简单,为了方便讲述,我们将采用16进制,写代码的时候在把它转回2进制就是了。 ...
  • RLE(Run LengthEncoding)行程长度压缩算法是一个简单高效的无损数据压缩算法,其基本思路是把数据看成一个线性序列,而这些数据序列组织方式分成两种情况:一种是连续的重复数据块,另一种是连续的不重复数据块。...
  • 一、二进制bin()在python中可以用bin()内置函数获取一个十进制的数的二进制计算机容量单位8bit = 1 bytes 字节,最小的存储单位,1bytes缩写为1B1KB = 1024B1MB = 1024KB1GB = 1024MB1TB = 1024 GB1PB = 1024 TB1EB ...
  • 虽然我们更喜欢称之为十六进制编辑器,但它确实有着很多诸如数据恢复、低级数据处理等其他强大的功能,当然了,这些高级功能同样是基于对十六进制数据的处理,需要有相当强悍的专业知识才能使用。 专业的 16 进制...
  • RLE压缩算法原理与C语言实现

    千次阅读 多人点赞 2020-06-06 09:30:34
    RLE压缩算法(下简称RLE算法)的基本思路是把数据按照线性序列分成两种情况:一种是连续的重复数据块,另一种是连续的不重复数据块。 RLE算法的原理就是用一个表示块数的属性加上一个数据块代表原来连续的若干块数据...
  • 从信息传输、加密解密、图像处理,到媒体编码、数据压缩、中继输出…二进制无处不在。二进制属于计算机科学中的「第一性原理」和基本常识之一,理解了二进制,就能串起计算机科学中很多看似不相关的领域。 1. ASCII...
  • 【转】HTTP传输二进制 数据编码解码

    千次阅读 2017-07-03 18:41:04
    【转】HTTP传输二进制初探 从第一次接触http协议的时候,不知是怎么回事,形成了这么一个错误的观点,认为http协议是个纯ASCII字符协议,也就是说在http流里是看不到二进制流的0x00值的。其实答案是:http协议...
  • 本文总结如何对数字进行进制转换与位运算
  • [9] 25 =======recursion base trans========= 1456 from 10 to 16: 5B0 32 from 10 to 2: 100000 Process finished with exit code 0 使用python解决算法和数据结构--使用栈实现进制转换 可以将10进制数据转换成2...
  • 在之前的文章([算法系列之十六]数据压缩之游程编码)中,我们知道了如何压缩一段重复元素组成的数据。这种压缩称为“游程编码”,该算法在无损数据压缩传输时非常方便。但问题是数据必须遵循特定格式。比如,字符串...
  • 针对网络能耗和延迟问题,提出了一种基于免疫代理的数据融合算法。通过代理的自由迁移降低节点传输能耗;...采用十六进制编码方法对融合数据进行压缩处理。试验结果表明,该算法能有效降低网络能耗和延迟。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 13,377
精华内容 5,350
关键字:

十六进制数据压缩算法