精华内容
下载资源
问答
  • 信源站
    2021-06-30 02:34:16

    江苏省计算机一级B 考试知识点整理(理论宝典) (2010 年3 月1 日)

    第1章 信息技术概述

    考点1:什么是信息?

    既不是物质也不是能量,是一种资源。

    客观上:信息是指事物运动状态及状态变化的方式;

    主观上:信息是认识主体所感知或所表述的事物运动及其变化方式的形式、内容和效用。

    考点2:信息处理包含哪些行为和活动?

    信息的收集,加工,存储,传递,施用。

    考点3:什么是信息技术?什么是信息处理系统?

    信息技术 (Information Technology,简称IT)指的是用来扩展人们信息器官功能、协助人们有效地进行信息处理的一类技术。

    现代信息技术的主要特征:

    是以数字技术为基础,

    以计算机及其软件为核心,【采用电子技术(包括激光技术)进行信息的收集、加工、存储、显示与控制,它包括通信、广播、

    计算机、微电子、遥感遥测、自动控制、机器人等诸多领域。】

    信息处理系统:用于辅助人们进行信息获取、传递、存储、加工处理、控制及显示的综合使用各种信息技术的系统。

    例:雷达(感测,识别系统)电话(点对点,双向系统)广播(点到多点,单向系统)

    重点:因特网则是一种跨越全球的多功能信息处理系统。

    考点4 :集成电路

    根据它所包含的电子元件数目可以分为小规模、中规模、大规模、超大规模和极大规模集成电路 (目前CPU )。

    考点5:通信的概念及通信系统的组成。

    各种信息的传递称为通信。现代通信是指使用电波或光波传递信息的技术。通信的基本任务是传递信息,

    至少需三个要素组成,即:信息的发送者(称为信源)、数字 模拟:调制

    信息的接收者(称为新宿)模拟 数字:解调

    信息的传输通道(称为信道)。信号有连续信号(模拟信号)和离散信号(数字信号)之分。

    易错题:当前计算机中使用的集成电路绝大部分是模拟电路。F

    考点6:传输介质

    通信分有线通信和无线通信两类。

    有线通信系统中使用的传输介质有金属导体 (同轴电缆、双绞线等)和光导纤维;

    无线通信使用电磁波 (无线电波、微波、红外线、激光等)。

    重点:卫星通信是利用:地球卫星作为中继站来转发无线电信号的通信。

    考点7:移动通信

    第一代个人移动通信系统采用的是模拟技术,例:大哥大。

    第二代移动通信系统采用的数字传输技术,现行的 GSM、CDMA 手机。【已经大规模普及!大部分人正在使用的就是!

    注意】

    第三代移动通信系统 (3G )将实现高质量的多媒体通信,包括话音、数据和图像通信等。【正在大规模普及:电信

    CDMA2000,联通WCDMA ,移动TD-SCDMA,WiMAX 】

    考点8 :数字技术

    当代电子信息技术的基础有两项:一项是微电子与光纤技术,

    另一项是数字技术。

    磁盘是利用磁介质表面区域的磁化状态来存储二进位信息,

    光盘则是通过“刻”在盘片光滑表面上的微小凹坑来记录二进位信息。

    1 / 8

    一级B 考试知识点整理

    比特是计算机和其他数字系统处理、存储和传输信息的最小单位。一般用小写字母“b”表示。

    字节byte :1byte=8bit

    存储容量是存储器的一项重要指标。计算机内存储器容量通常使用2 的幂次作为单位,因为这有助于存储器的设计。

    千字节(kilobyte ) 1KB=210 字节=1024B

    兆字节(megabyte ) 1MB=220 字节=1024KB

    吉字节(gigabyte ) 1GB=230 字节=1024MB

    太字节(terabyte ) 1TB=240 字节=1024GB

    比特的传输:在数据通信和计算机网络中传输二进位信息时,由于是一位一位串行传输的,传输速率的度量单位是每秒多少比特,且

    kilo 、mega 、giga 等也作为10 的幂次计算。经常使用的传输速率单位如下:

    比特/秒(b/s) ,也称“bps” ,

    千比特/

    更多相关内容
  • 数字视频技术广泛应用于通信、计算机、广播电视等领域, 带来了会议电视、可视电话及数字电视、媒体...下面就长治微波在数字微波传输系统改造后, 探讨EN2200- M型编码器及数字电视信源编解码技术和应用。  1 数字电
  • 第二代移动通信系统基站设备的典型设计方案是将接收天线、发射天线安装在室外,将射频收发信机安装在室内,...同样,数字光纤直放也可通过光纤传送基带信号,两者既有区别,又有联系。 1RRU工作原理及应用

    第二代移动通信系统基站设备的典型设计方案是将接收天线、发射天线安装在室外,将射频收发信机安装在室内,射频收发信机与接收天线、发射天线间用低损耗的射频电缆连接。这就是所谓射频拉远技术。从第三代移动通信系统开始,结合射频拉远技术,诞生了新型信号传输设备RRU,通过光纤传输基带信号。同样,数字光纤直放站也可通过光纤传送基带信号,两者既有区别,又有联系。


    1RRU工作原理及应用


      射频拉远单元RRU(RemoteRadioUnit)带来了一种新型的分布式网络覆盖模式,它将大容量宏蜂窝基站集中放置在可获得的中心机房内,基带部分集中处理,采用光纤将基站中的射频模块拉到远端射频单元,分置于网络规划所确定的站点上,从而节省了常规解决方案所需要的大量机房;同时通过采用大容量宏基站支持大量的光纤拉远,可实现容量与覆盖之间的转化。




      RRU的工作原理是:基带信号下行经变频、滤波,经过射频滤波、经线性功率放大器后通过发送滤波传至天馈。上行将收到的移动终端上行信号进滤波、低噪声放大、进一步的射频小信号放大滤波和下变频,然后完成模数转换和数字中频处理等。系统框图如(图1)所示。



      RRU同基站接口的连接接口有两种:CPRI(CommonPublicRadioInterface通用公共射频接口)及OBASI(OpenBaseStationArchitectureInitiative开放式基站架构)。其中,CPRI组织成员包括:爱立信、华为、NEC、北电、西门子。OBSAI组织成员包括:诺基亚、中兴、LGE、三星、Hyundai。RRU同RNC连接图如(图2)所示。



      信号覆盖方式上,RRU可通过同频不同扰码方式,从NodeB引出。也可通过同频不同扰码方式,从RNC引出。这两种覆盖方式都是常规的方式,除此之外,对于3扇区,但配有多余信道板以及多余基带处理设备的基站可以利用基带池共享技术,将多余的基带处理设备设为第4小区,如图3所示。图中SC为扰码I/Q射频调制解调,SCH为同步码。




    数字光纤直放站原理及应用


      数字光纤直放站不同于以往的模拟光纤直放站,它将RF信号经变频处理变为中频数字信号,再通过光纤拉远进行传输。其具体工作原理是:近端机将从NodeB接收到的基站下行信号通过耦合,下变频处理,到基带变为I/Q信号或低中频信号,这种信号经ADC变换到数字信号后按一定帧格式打包成串行数据,再经光纤发送到远端机。远端机经基带处理单元解帧,恢复I/Q或低中频信号,这种信号经DAC变换到模拟信号,再上变频到射频,经发射子系统发射出去;远端机将接收到的移动终端上行信号通过上述逆过程,上送至基站接收端。


      近端机完成对基站信号的获取和发送,远端机完成对移动终端机信号的获取和发送,近端机与远端机之间的接口为CPRI,数字传送采用以太网的标准光纤收发器。系统框图如(图4)所示。



      数字光纤直放站对信号覆盖的方式,同以往模拟直放站类似,可通过光纤直连一拖一(一个近端加一个远端)使用,也可通过光分路器进行一拖多(一个近端加多个远端)覆盖使用。如(图5)所示。



    RRU同数字光纤直放站的分析比较



      RRU同数字光纤直放站都可利用现有成熟的以太网数字光纤传输技术传输基带信号,并共同遵守标准的CPRI和OBSAI接口。使用中可实现RRU和数字光纤直放站的远端机的互相替换。


      两者均可作为室内分布系统的信号源,选用哪一种取决于宏基站的载频数量和该室内业务量需求。如果宏基站载频多、容量很富裕,用数字光纤直放站拉远更合适,同时可减少扇区扰码。如果该室内业务量需求较大应选用RRU作信号源。如果业务量需求很大,如大型写字楼、会展中心等,应考虑数字光纤直放站、RRU和宏基站的联合组网。


      在覆盖距离上,两者均可作为基站拉远系统供用,数字光纤直放站用作载波池拉远,RRU可用作基带池拉远。载波池拉远距离取决于小区覆盖半径和光在光纤上的传输速度,数字信号在光纤中传播,其动态范围也较模拟信号大,这样就可以实现远端机更大的信号覆盖;同时,数字信号不随光信号的衰减而衰减,因此其传输(拉远)距离也进一步增加了。经计算,最远可达40km以上,用作基带池拉远的RRU基本不受距离限制,可拉得更远。


      在组网方式上,RRU作为拉远单元可单独使用,而数字光纤直放站由近端机和远端机组成,在实际应用时,近端机是一个,而远端机可以是一个或多个,组网上可并联也可串联,组网方式也可以多样化,如:菊花链形、环形、树形等等。


      在扰码的使用上,数字光纤直放站射频信号的扰码总是同施主基站的扰码相同,数字光纤直放站也不增加基站信道板硬件容量和正交码容量,所以在扇区内大量采用并不会增加扰码。射频拉远单元RRU是利用基站剩余的信道板和基带处理设备组成新的扇区,通过光纤系统拉到远处,有人称它为基带池技术,也有人叫它拉远的微蜂窝技术,总之,它具有硬件容量,并且拥有新的扰码和同步码。由于RRU具有基站性能,在宏基站的扇区内大量采用必然会增加很多扰码和邻区列表,会发生导频污染,软切换增加。如(图6)所示。在网络优化时这是必须注意的问题。



      在传输时延上,数字光纤直放站的传输时延比较大,因为存在两次变频过程。而RRU直接传送基带信号,时延不明显。


      在底噪抬升上,数字光纤直放站仅采用ADC和DAC,此过程只可能引入更多的量化噪声,从而抬升上行噪声。而RRU传输的为纯基带信号,可不用考虑底噪问题。


      从成本上,采用RRU技术,可以节省常规建网方式中需要的大量机房,节约基带单元的投资。RRU体积小,重量轻,可以应用于城区机房条件不理想或者机房匮乏的情况,但是应用前提是需要有光纤进行传输。但在价格方面,RRU比直放站要贵1/3左右。对于一拖一的系统,数字光纤直放站成本优势不明显,但一拖多,成本优势就比较明显了。



    结语:



      通过以上分析中可以看出,数字光纤直放站和RRU各自都有其优势,同为3G时代的新产品。3G发牌在即,两者都列入重要手段统一网络规划,以达到预期的良好效果。


    延伸系统和拉远系统的比较:


      以延伸系统常见的直放站为例(非光线直放站)与3GRRU比较


      1、直放站没有容量,拉远是可以带容量的系统。


      2、直放站会对施主基站造成干扰,而拉远站则是本站的一个扇区,不会产生干扰。


      3、直放站有效距离有限,拉远站的有效距离在40公里以内。


      4、直放站的故障率是在17%左右,拉远站目前的故障率在3%左右。


      5、直放站容易自激,拉远站涉及不到该问题。


      6、直放站在断电掉站重起后不易起站,拉远站则不会有此种情况。


      传统的光纤直放站就是耦合一部分基站模拟信号并用光纤传输到远端后转为成模拟信号在放大输出。这种应用方式在目前的3G的实验网络以及一些规划中已经很少看见了。


      而一些新的概念产生了,首先是很多基站厂家提出了光纤射频拉远的概念(RRU),这种概念又分数字光纤拉远和射频光纤拉远。其中射频光纤拉远的概念可能和传统的光纤直放站改动不大,区别是基站本身并没有功放和低噪放了,直接通过低功率射频接口光模块,这样也就没有以前所谓的耦合和接负载的概念了。而数字拉远的话,是直接将基站的数字信号拉远,射频部分全部在远端。


      另外一个概念叫做基站池的概念,就是所有基站包括各类制式的基站全部集中在一个机房之中,各种制式的信号通过射频合路后通过LI接口变为光信号,在通过光纤传输到各个需要覆盖的地方,远端同样有一个RRU(或者多个不同制式的RRU),这样方案大大节约了建网成本,方便了运营商统一管理基站和远端设备。


      以上是光纤直放站在3G应用中的变形思路,希望各位同仁谈谈自己的看法,认为那种方案更适合3G的网络建设。


    拉远站和直放站有什么区别


      射频拉远,是将基带信号转成光信号传送,在远端放大。

     

      直放站就是将无线信号转成光信号传送。


      区别就是直放站会将噪声同时放大,而射频拉远则不会。只要是做过光纤直放站的都知道!!拉远的就是把基站的基带单元和射频单元分离,两者之间传输的是基带信号,而光纤直放站是从基站的射频输出口耦合出射频信号转换为光信号在光纤中传输,然后远端再转为射频放大!!高效的RRH(射频拉远)


      射频拉远单元(RRU)


    基带传输:


      由计算机或终端产生的数字信号,频谱都是从零开始的,这种未经调制的信号所占用的频率范围叫基本频带(这个频带从直流起可高到数百千赫,甚至若干兆赫),简称基带(baseband)。这种数字信号就称基带信号。举个简单的例子:在有线信道中,直接用电传打字机进行通信时传输的信号就是基带信号。而传送数据时,以原封不动的形式,把基带信号送入线路,称为基带传输。基带传输不需要调制解调器,设备费用低,适合短距离的数据输,比如一个企业、工厂,就可以采用这种方式将大量终端连接到主计算机。另外就是传输介质,局域网中一般都采用基带同轴电缆作传输介质。


    频带传输:


      上面的传输方式适用于一个单位内部的局域网传输,但除了市内的线路之外,长途线路是无法传送近似于0的分量的,也就是说,在计算机的远程通信中,是不能直接传输原始的电脉冲信号的(也就是基带信号了)。因此就需要利用频带传输,就是用基带脉冲对载波波形的某些参量进行控制,使这些参量随基带脉冲变化,这就是调制。经过调制的信号称为已调信号。已调信号通过线路传输到接收端,然后经过解调恢复为原始基带脉冲。这种频带传输不仅克服了目前许多长途电话线路不能直接传输基带信号的缺点,而且能实现多路复用的目的,从而提高了通信线路的利用率。不过频带传输在发送端和接收端都要设置调制解调器。


      拉远就是将基站中的某些模块分离出来,使其远离基站部分。这样做的目的是如果在天线和基站直接直接使用射频线传输信号,则连接到基站的线路较多,且基站功能复杂多选择站地址有很高的要求。


    中频拉远:


      即将无线基站中的模拟射频收发部分与无线基站的基带数字信号处理部分在模拟中频处分开,形成远端射频前端设备与室内单元。中频拉远技术通过基站室内单元的模拟中频接口,将射频的收发信机拉远至天线附近。下行方向将中频信号传输到射频前端,经混频后转换为射频信号,再由天线发射;上行方向将从天线发射过来的射频信号在前端混频为中频信号,通过中频传输系统传回到基站室内单元。远端射频前端设备与室内单元间可以用有线和无线传输手段相连接。其介质可以是中频电缆、光纤等。与传统的射频拉远技术相比,中频拉远技术具有以下显著的优点:电缆数量少、传输距离远、组网灵活、成本大幅降低等。


    同理基带拉远


      同理基带拉远:即将基站BBU和RRU之间传输基带信号。这样可以使用光纤来传输了。


      基带拉远基站采用光纤传输,而射频拉远则采用同轴电缆,光纤的成本是低于电缆的。但是,基带拉远并不是光靠光纤就能解决的,在拉远中还需要光模块,而且光模块价格不菲,按三个扇区考虑,采用基带拉远进行本地拉远时一般需要6个或12个光模块,取决于每扇区的RRU数量,所以,基带拉远的整体价格并不比射频拉远有优势。


      “基带拉远基站确实能解决没有机房的问题,但是其不能解决天面的问题。基带拉远基站其BBU和RRU的连接媒介是裸光纤,裸光纤资源比机房资源更难以协调,铺设起来也需要在时间和成本方面付出昂贵的工程代价。”


      由于射频拉远和中频拉远只能使用电缆来实现拉远,拉远距离有限,分别达100米和300米左右,所以只能实现本地拉远,即其机房和天面在一个楼宇的拉远;而基带拉远可以使用光纤进行拉远,传输距离一般可达5Km以上,除了可以实现本地拉远外,也能实现远端拉远,而远端拉远是指机房和天面不在同一个楼宇,中间的距离比较远。


      光纤拉远有时是中间有个站出问题了采用的,而直放站是为了增加覆盖用的。


      拉远站是将基带处理和射频分离,是信源;直放站仅是对信源基站的延伸,不是信源。


      一个是基站有独立的传输,有属于自己的小区,一个是放大器,只是放大他人小区的信号;


      或许你要问的是RRU和光纤直放站的区别~~~


    RRU相当于载波和CUD的作用


      拉远站,可以提供有用信道,主要是射频部分拉远,便于覆盖简单有效。而直放站不能提供有效信道,只能做信号延伸,投资少,安装方便。


      拉远站是通过光纤近端设备将信号光电转换后经光纤传输到远端,再由远端的设备将光信号转换成电信号再放大后重发到覆盖区的设备。其它拉远站你也可以把它看作是一种光纤直放站!


      直放站是一个类,包括同频,移频,光纤等多种类型!


      拉远站就是通过光纤连接的光纤站,直放站有光纤直放站和无线直放站。


      射频拉远RRU相当于一个扇区了


      而直放站只是扇区的一部分:)


      简单的说射频拉远就是把一个天线拉到里机房很远的地方


      直放站是把一个天线的一部分信号拉到特定的地方


      射频拉远就是近远端之间用射频信号将信号拉远。


      光纤直放站就是近远端之间用光信号传输。


    区别:两者延伸信号的中继端采用方式不一样


      W网中。基带单元就是BBU+射频单元RRU,BBU就相当交换分配单元,RRU就是载波!通过光纤连接起来!


      G网中射频拉远(爱立信)MU+RRU,有可能各厂家叫法不同,拉远比如说,某一条隧道在不可能建机房的情况下,拉过光纤的方式把RRU拉进隧道进行覆盖!不拉远区别可想而知!


      小区容量取决于两者!价格不讨伦!


      WCDMA中所谓的BBU+RRU就是分布式基站,与宏基站不同,分布式基站比较小巧。


      BBU为基带处理单元、RRU为射频模块


      G网中叫什么每个厂家不知道是不是一样


      射频拉远设备就是RRU,RRU(RadioRemoteUnit)技术特点是将基站分成近端机即无线基带控制(RadioServer)和远端机即射频拉远(RRU)两部分,二者之间通过光纤连接,其接口是基于开放式CPRI接口,可以稳定地与主流厂商的设备进行连接。RS可以安装在合适的机房位置,RRU安装在天线端,这样,将以前的基站模块的一部分分离出来,通过将RS与RRU分离,可以将烦琐的维护工作简化到RS端,一个RS可以连接几个RRU,既节省空间又降低成本,提高组网效率。


      连接近、远端采用光纤传输。


      射频拉远就是结合了微蜂窝和光纤直放站的优点,各取所长!

    展开全文
  • XYCMS企业建系统是以asp+access进行开发的企业建系统。 网站功能: 安全性:防SQL注入,自动锁定入侵的IP地址,防XSS攻击,具有很好的过滤系统 功能简述: 企业信息管理:包括基本
  • 用粒子滤波对2个接收机的来波方位角进行联合估计,并通过非线性映射得到信源位置坐标估计,实现了方位角计算与双定位的集成。仿真实验表明,当稳定分布参数 a 为1.4(中等脉冲程度)时,所提方法在低信噪比下的顽...
  • 该设备为G网数字分布式系统,采用了数字中频技术和千兆以太网协议,能够有效地放大信源信号,滤除其它干扰信号,防止其他小区干扰,达到最佳的远端覆盖效果。 本文档包含爱立信GSM网络分布式皮设备的安装和调测
  • Word版可编辑-信息论与编码课程设计报告统计信源熵与香农编码精心整理.doc下载提示(请认真阅读)1.请仔细阅读文档,确保文档完整性,对于不预览、不比对内容而直接下载带来的问题本不予受理。2.下载的文档,不会...

    44cb7578e1df5412b94317daaa3307ba.gifWord版可编辑-信息论与编码课程设计报告统计信源熵与香农编码精心整理.doc

    下载提示(请认真阅读)1.请仔细阅读文档,确保文档完整性,对于不预览、不比对内容而直接下载带来的问题本站不予受理。

    2.下载的文档,不会出现我们的网址水印。

    3、该文档所得收入(下载+内容+预览)归上传者、原创作者;如果您是本文档原作者,请点此认领!既往收益都归您。

    文档包含非法信息?点此举报后获取现金奖励!

    下载文档到电脑,查找使用更方便

    10

    积分

    还剩页未读,继续阅读

    关 键 词:Word

    编辑

    信息论

    编码

    课程设计

    报告

    统计

    信源

    香农

    精心

    整理

    资源描述:

    河南理工大学课程设计报告

    信息论与编码课程设计报告

    设计题目: 统计信源熵与香农编码

    专业班级 电 信 12-06

    学 号

    学生姓名

    指导教师

    教师评分

    2015年 3 月 30日

    目 录

    一、设计任务与要求2

    二、设计思路2

    三、设计流程图3

    四、程序运行及结果4

    五、心得体会6

    参考文献7

    附录:源程序8

    - 12 -

    一、设计任务与要求

    1.统计信源熵

    要求:统计任意文本文件中各字符(不区分大小写)数量,计算字符概率,并计算信源熵。

    2.香农编码

    要求:任意输入消息概率,利用香农编码方法进行编码,并计算信源熵和编码效率。

    二、设计思路

    本次课程设计中主要运用C语言编程以实现任务要求,分析所需要的统计量以及相关变量,依据具体公式和计算步骤编写语句,组成完整C程序。

    1、信源熵

    定义:信源各个离散消息的自信息量的数学期望为信源的平均信息量,一般称为信源的信息熵,也叫信源熵或香农熵,有时称为无条件熵或熵函数,简称熵,记为H()。

    计算公式:

    2、香农编码过程:

    (1)将信源消息符号按其出现的概率大小依次排列为

    (2)确定满足下列不等式的整数码长为

    (3)为了编成唯一可译码,计算第i个消息的累加概率

    (4)将累计概率变换成二进制数。

    (5)取二进制数的小数点后位即为该消息符号的二进制码字。

    3、 设计流程图

    1、 统计信源熵

    开始

    读取给定文件

    判断文件是否打开 否

    并且不为空

    统计文本字符,直 关闭文件

    至文本字符读完。

    统计同一字符(不分

    大小写)出现的次数

    计算字符概率

    计算信源熵

    输出

    结束

    2、香农编码

    开始

    输入概率

    计算累加概率

    计算码字

    计算码长

    计算平均码长

    计算信源熵

    计算编码效率

    输出

    结束

    四、 程序运行及结果

    1、统计信源熵

    2、 香农编码

    五、心得体会

    通过这次课程设计明显的体会到知识匮乏所带来的种种问题,首先是对C语言编程的不熟练,课程知识在与C语言的结合中没有清晰的思路,具体实现程序语言的编写较为困难。在程序的调试中出现的问题无法及时快速的解决,有些错误甚至无法找到合适的解决方法,以至于不断的修改程序,浪费了大量的时间。

    在设计期间出现的问题还是非常多的,要求熟悉相关软件的操作使用,需要不断的搜集所需的各种资料,及时解决遇到的问题。课程设计很是考察个人能力和团队合作协调能力,在面对自己所不熟悉甚至不了解的问题时,是怎样一步步的设计完成给定的任务,及时有成效的解决面临的问题的。从整体的分析设计到后面语句变量的敲定最终完成课题是对自己极其有益的锻炼,从中收获的不仅是知识上的,也是学习经验的积累和思维能力的提升,虽然一次课程设计任务不是那么繁重,可是认真去完成其中的一个个细节也是一种难得的体验。

    参考文献

    [1]曹雪虹,张宗橙.《信息论与编码》清华大学出版社.2009.

    [2]贾宗璞,许合利.《C语言程序设计》人民邮电出版社.2010.

    [3]盛骤,谢式千,潘承毅.《概率论与数理统计》[M].高等教育出版.1989.

    附录:源程序

    1、 统计信源熵

    #include #include #include /*memcpy所需头文件*/

    #include #define N 1000/*宏定义N,此处N代表读取文本文件最大字符数为1000*/

    int main(void)

    {

    char s[N],M[N];

    int i = 0,j=0,n=0,L=0;

    int len, num[27] = {0};

    double result=0,p[27]= {0};

    FILE *f;

    char temp[N];

    /********打开文件.txt*******/

    if(!(f = fopen("D:\\VC++6.0\\text518.txt","rb")))

    { printf("文件打开失败!\n");

    return 0;

    }

    while(!feof(f))/*feof检查文件是否结束。如结束,否则返回0.*/

    {

    len=fread(temp,1,1000,f);/*fread返回读取的字符个数。从f锁指定的文件中读取长度为1的1000个数据项,存到temp所指向的内存区。返回所读取的数据个数。*/

    }

    fclose(f);/*关闭f所指向的文件*/

    temp[len]=\0;/*将temp数组元素清空(\0空字符)*/

    memcpy(s,temp,sizeof(temp)); /*从temp中拷贝sizeof个字节到目标s中。sizeof返回一个对象或者类型所占的内存字节数*/

    /*****计算各个字母、空格出现数目*****/

    for(i=0; i=a&&s[i]<=z)

    num[s[i]-97]++;

    else

    if(s[i]>=A&&s[i]<=Z)

    num[s[i]-65]++;

    }

    printf("文本文件中各字符(不区分大小写)数量:\n");

    for(j=0; j<26; j++)

    {

    M[j]=num[j];

    printf("%4c:%d\t",j+65,M[j]);/*输出格式,%3c在该字符前在空三个空格*/

    L++;

    if(L==5)/*输出格式,每行五个字母*/

    {

    printf("\n");

    L=0;

    }

    }

    printf("空格:%d\t",num[26]);

    /*****计算各个字母、空格出现概率****/

    printf("\n文本文件中各个字符概率:\n");

    for(i=0; i<26; i++)

    {

    p[i]=(double)num[i]/strlen(s); printf("%3c:%f\t",i+65,p[i]);

    n++;

    if(n==5)/*输出格式,每行五个字母概率*/

    {

    printf("\n");

    n=0;

    }

    }

    p[26]=(double)num[26]/strlen(s);

    printf("空格:%f\t",p[26]);

    printf("\n");

    /**********计算信源熵**********/

    for(i=0; i<27; i++)

    {

    if (p[i]!=0)

    result=result+p[i]*log(p[i])*1.433;/*信源熵,I(x)=-logp(x)*/

    }

    result=-result;

    printf("信源熵为:%f",result);

    printf("\n");

    return 0;

    }

    2、 香农编码

    #include #include #include #define max_CL 10 /*最大容量的代码的长度*/

    #define max_PN 6 /*输入序列的个数*/

    typedef float datatype;

    typedef struct SHNODE {

    datatype pb; /*第i个消息符号出现的概率*/

    datatype p_sum; /*第i个消息符号累加概率*/

    int kl; /*第i个消息符号对应的码长*/

    int code[max_CL]; /*第i个消息符号的码字*/

    struct SHNODE *next;

    }shnolist;

    datatype sym_arry[max_PN]; /*序列的概率*/

    void pb_scan(); /*得到序列概率*/

    void pb_sort(); /*序列概率排序*/

    void valuelist(shnolist *L); /*计算累加概率码长码字*/

    void codedisp(shnolist *L);

    void pb_scan()

    {

    int i;

    datatype sum=0;

    printf("input %d possible!\n",max_PN);

    for(i=0;i>");

    scanf("%f",&sym_arry[i]);

    sum=sum+sym_arry[i];

    }

    /*判断序列的概率之和是否等于1在实现这块模块时scanf()对float数的缺陷故只要满

    足0.991.0001||sum<0.99)

    { printf("sum=%f,sum must (<0.999max)

    {

    max=sym_arry[j];

    pos=j;

    }

    sym_arry[pos]=sym_arry[i];

    sym_arry[i]=max;

    }

    }

    void codedisp(shnolist *L)

    {

    int i,j;

    shnolist *p;

    datatype hx=0,KL=0; /*hx存放序列的熵的结果KL存放序列编码后的平均码字的

    结果*/

    p=L->next;

    printf("num\tgailv\tsum\t-lb(p(ai))\tlenth\tcode\n");

    printf("\n");

    for(i=0;ipb,p->p_sum,-3.332*log10(p->pb),p->kl);

    j=0;

    for(j=0;jkl;j++)

    printf("%d",p->code[j]);

    printf("\n");

    hx=hx-p->pb*3.332*log10(p->pb); /*计算消息序列的熵*/

    KL=KL+p->kl*p->pb; /*计算平均码字*/

    p=p->next;

    }

    printf("H(x)=%f\tKL=%f\nR=%fbit/code",hx,KL,hx/KL); /*计算编码效率*/

    }

    shnolist *setnull()

    { shnolist *head;

    head=(shnolist *)malloc(sizeof(shnolist));

    head->next=NULL;

    return(head);

    }

    shnolist *my_creat(datatype a[],int n)

    {

    shnolist *head,*p,*r;

    int i;

    head=setnull();

    r=head;//87

    for(i=0;ipb=a[i];

    p->next=NULL;

    r->next=p;

    r=p;

    }

    return(head);

    }

    void valuelist(shnolist *L)

    {

    shnolist *head,*p;

    int j=0;

    int i;

    datatype temp,s;

    head=L;

    p=head->next;

    temp=0;

    while(jp_sum=temp;

    temp=temp+p->pb;

    p->kl=-3.322*log10(p->pb)+1;

    /*编码*/

    {

    s=p->p_sum;

    for(i=0;ikl;i++)

    p->code[i]=0;

    for(i=0;ikl;i++)

    {

    p->code[i]=2*s;

    if(2*s>=1)

    s=2*s-1;

    else if(2*s==0)

    break;

    else s=2*s;

    }

    }

    j++;

    p=p->next;

    }

    }

    int main(void)

    {

    shnolist *head;

    pb_scan();

    pb_sort();

    head=my_creat(sym_arry,max_PN);

    valuelist(head);

    codedisp(head);

    }

    展开阅读全文

    温馨提示:

    1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。

    2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。

    3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。

    4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。

    5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。

    6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。

    7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

    bb6249c6567dd4384e6ab3556cfc22ed.gif 

    人人文库网所有资源均是用户自行上传分享,仅供网友学习交流,未经上传用户书面授权,请勿作他用。

    关于本文

    本文标题:Word版可编辑-信息论与编码课程设计报告统计信源熵与香农编码精心整理.doc

    链接地址:https://www.renrendoc.com/p-34969447.html

    展开全文
  • 信息论实验-信源编码2(Lz编码和算数编码的C++实现)

    万次阅读 多人点赞 2017-08-13 17:21:36
    在算法理解上我借助了一些网友前辈的博客中的例子,文章最后我也会指出引用了那些文章,谢谢前辈们给出的经典的例子能让晚辈在巨人的肩膀上,所以在此声明,希望我的引用不会侵犯到前辈们的权益 * 先上源代码*...

    上一篇文章给出了Huffman编码和Shannon Fano编码的编码原理以及C++的程序,程序可以用来实现给任意类型的文件进行无损压缩,缺点是比较耗时,不能作为正常的通用压缩软件来使用,但是作为算法理解,算法思路是没有问题的,后续可能需要进行优化,下面的LZ编码和算数编码和Huffman、Fano编码是走的截然不同的道路,他们的思想差别很大,但却殊途同归,在算法理解上我借助了一些网友前辈的博客中的例子,文章最后我也会指出引用了那些文章,谢谢前辈们给出的经典的例子能让晚辈站在巨人的肩膀上,所以在此声明,希望我的引用不会侵犯到前辈们的权益
    * 先上源代码*
    信源编码源代码

    第三章:算数编码的实现

    一. 算数编码的原理

    算数编码不同于Huffman编码,它是非分组(非块)码。它从全序列出发,考虑符号之间的依赖关系来进行编码的。
    算数编码主要的编码方法正是计算输入信源符号序列所对应的区间。术编码的基本原理是将编码的消息表示成实数0和1之间的一个间隔(Interval),消息越长,编码表示它的间隔就越小,表示这一间隔所需的二进制位就越多。
    算术编码用到两个基本的参数:符号的概率和它的编码间隔。信源符号的概率决定压缩编码的效率,也决定编码过程中信源符号的间隔,而这些间隔包含在0到1之间。编码过程中的间隔决定了符号压缩后的输出。
    给定事件序列的算术编码步骤如下:
    (1)编码器在开始时将“当前间隔” [ L, H) 设置为[0,1)。
    (2)对每一事件,编码器按步骤(a)和(b)进行处理
    (a)编码器将“当前间隔”分为子间隔,每一个事件一个。
    (b)一个子间隔的大小与下一个将出现的事件的概率成比例,编码器选择子间隔对应于下一个确切发生的事件相对应,并使它成为新的“当前间隔”。
    (3)最后输出的“当前间隔”的下边界就是该给定事件序列的算术编码。
    设Low和High分别表示“当前间隔”的下边界和上边界,CodeRange为编码间隔的长度,LowRange(symbol)和HighRange(symbol)分别代表为了事件symbol分配的初始间隔下边界和上边界。算术编码也是一种对错误很敏感的编码方法,如果有一位发生错误就会导致整个消息译错。
    算术编码可以是静态的或者自适应的。在静态算术编码中,信源符号的概率是固定的。在自适应算术编码中,信源符号的概率根据编码时符号出现的频繁程度动态地 进行修改,在编码期间估算信源符号概率的过程叫做建模。需要开发动态算术编码的原因是因为事先知道精确的信源概率是很难的,而且是不切实际的。当压缩消息 时,我们不能期待一个算术编码器获得最大的效率,所能做的最有效的方法是在编码过程中估算概率。因此动态建模就成为确定编码器压缩效率的关键。

    二. 算数编码过程

    假设有信源符号{A, B. C, D}, 对应的概率和初始编码间隔如下表所示

    符号ABCD
    概率01.0.40.20.3
    初始编码间隔[0, 0.1)[0.1, 0.5)[0.5, 0.7)[0.7, 1)

    如果二进制消息序列的输入为:CADACDB。编码时首先输入的符号是C, 找到他的编码范围是[0.5, 0.7)。由于消息由于消息中第二个符号A的编码范围是[0, 0.1),因此它的间隔就取[0.5, 0.7)的第一个十分之一作为新间隔[0.5, 0.52)。依此类推,编码第3个符号D时取新间隔为[0.514, 0.52),编码第4个符号A时,取新间隔为[0.514, 0.5146),…。消息的编码输出可以是最后一个间隔中的任意数
    编码过程如下表所示
    表3.2 算数编码的编码过程

    步骤输入符号编码间隔编码判决
    1C[0.5, 0.7]符号的间隔范围[0.5, 0.7]
    2A[0.5, 0.52][0.5, 0.7]间隔的第一个1/10
    3D[0.514, 0.52][0.5, 0.52]间隔的最后一个1/10
    4A[0.514, 0.5146][0.514, 0.52]间隔的第一个1/10
    5C[0.5143, 0.51442][0.514, 0.5146]间隔的第五个1/10开始,二个1/10
    6D[0.514384, 0.51442][0.5143, 0.51442]间隔的最后3个1/10
    7B[0.5143836,0.514402][0.514384,0.51442]间隔的4个1/10,从第1个1/10开始
    8从[0.5143876, 0.514402]中选择一个数作为输出:0.5143876

    译码过程如下表
    表3.3 算数编码的译码过程

    步骤间隔译码符号译码判决
    1[0.5, 0.7]C0.51439在间隔 [0.5, 0.7)
    2[0.5, 0.52]A0.51439在间隔 [0.5, 0.7)的第1个1/10
    3[0.514, 0.52]D0.51439在间隔[0.5, 0.52)的第7个1/10
    4[0.514, 0.5146]A0.51439在间隔[0.514, 0.52]的第1个1/10
    5[0.5143, 0.51442]C0.51439在间隔[0.514, 0.5146]的第5个1/10
    6[0.514384, 0.51442]D0.51439在间隔[0.5143, 0.51442]的第7个1/10
    7[0.51439,0.5143948]B0.51439在间隔[0.51439, 0.5143948]的第1个1/10
    8译码的消息:C A D A C D B

    三. 算数编码的实现

    这几种算法唯独算数编码我没有用C++实现,当时记得为了应付课堂作业,借用了网上一位博友的代码,大家如果想借鉴这个算法实现的代码,我这里可以给出我更改后的版本,但并不是我原创的,但是很抱歉具体是在哪里借鉴的我忘记了,当时比较草率,没有想太多,这里我还是把过程及测试结果给大家介绍清楚,代码的话如果能找到原主人最好不过了,这里我给出我改过的版本。
    算数编码我只是使用字符串进行了测试,不能做到像Huffman编码一样对任何类型的文件都进行编码和译码。
    主函数

    int main()
    {
        string str; //输入要编码的String类型字符串
        int number = 0, size = 0; //number--字符串中不重复的字符个数;size--字符串长度 
        char c[N]; //用于存储不重复的字符
        long double p[N], output; //p[N]--不重复字符的概率,output--编码结果 
        disp();
        cout << "输入要编码的字符串:";
        getline(cin, str); //输入要编码的字符串
        size = str.length(); //字符串长度
        number = proba(str, c, p, size);//调用求概率函数,返回不重复字符的个数
        cout.setf(ios::fixed); //“魔法配方”规定了小数部分的个数
        cout.setf(ios::showpoint); //在此规定编码结果的小数部分有十个
        cout.precision(10);//调用编码函数,返回编码结果
        output = bma(c, p, str, number, size);//调用译码函数,输出要编码的字符串,
        yma(str, c, p, number, size, output); //以验证编码是否正确   
        getchar();
        return 0;
    }

    特殊结构和功能函数的定义

    #define N 100 //输入的字符应该不超过50个
    struct L //结构用于求各字符及其概率
    {
        char ch; //存储出现的字符(不重复)
        int num; //存储字符出现的次数
        double f;//存储字符的概率
    };
    //显示信息
    void disp();
    //求概率函数,输入:字符串;输出:字符数组、字符的概率数组;返回:数组长度; int proba(string str,char c[],long double p[],int count);
    //求概率的辅助函数
    int search(vector<L> arch, char, int n);
    long double bma(char c[], long double p[], string str, int number, int size);
    int proba(string str, char c[], long double p[], int count);
    //编码函数,输入:字符串,字符数组,概率数组,以及数组长度;输出:编码结果 long double bma(char c[],long double p[],string str,int number,int size);
    //译码函数,输入:编码结果,字符串,字符数组,概率数组,以及它们的长度;输出:字符串
    //该函数可以用于检测编码是否正确
    void yma(string str, char c[], long double p[], int number, int size, long double input);
    
    void disp()
    
    {
    
        cout << endl;
        cout << "此程序只需要输入要编码的字符串,不需要输入字符概率\n";
        cout << endl;
    
    }
    
    //求概率函数
    
    int proba(string str, char c[], long double p[], int count)
    
    {
    
        cout.setf(ios::fixed); //“魔法配方”规定了小数部分位数为三位
        cout.setf(ios::showpoint);
        cout.precision(3);
        vector<L>pt; //定义了结构类型的向量,用于同时存储不重复的字符和其概率
        L temp; //结构类型的变量
        temp.ch = str[0]; //暂存字符串的第一个字符,它的个数暂设为1
        temp.num = 1;
        temp.f = 0.0;
        pt.push_back(temp); //将该字符及其个数压入向量
        for (int i = 1; i<count; i++)//对整个字符串进行扫描
    
        {
            temp.ch = str[i]; //暂存第二个字符
            temp.num = 1;
            temp.f = 0.0;
            for (int j = 0; j<pt.size(); j++) //在结构向量中寻找是否有重复字符出现
            { //若重复,该字符个数加1,并跳出循环 
                int k; //若不重复,则压入该字符,并跳出循环 
                k = search(pt, str[i], pt.size());
                if (k >= 0)
    
                {
                    pt[k].num++;
                    break;
                }
                else
                {
                    pt.push_back(temp);
                    break;
                }
    
            }
    
        }
        for (int i = 0; i<pt.size(); i++) //计算不重复字符出现的概率
        {
            pt[i].f = double(pt[i].num) / count;
        }
        int number = pt.size(); //计算不重复字符出现的次数
        cout << "各字符概率如下:\n";
        for (int i = 0; i<number; i++) //显示所得的概率,验证是否正确
        {
            if (count == 0)
            {
                cout << "NO sample!\n";
            }
            else
            {
                c[i] = pt[i].ch;
                p[i] = pt[i].f;
                cout << c[i] << "的概率为:" << p[i] << endl;
            }
        }
        return number; //返回不重复字符的个数
    }
    //求概率的辅助函数
    //若搜索发现有重复字符返回正数
    //否则,返回-1
    int search(vector<L> arch, char ch1, int n)
    {
        for (int i = 0; i<n; i++)
        {
            if (ch1 == arch[i].ch) return i;
        }
    return -1;
    }
    //编码函数
    long double bma(char c[], long double p[], string str, int number, int size)
    {
        long double High = 0.0, Low = 0.0, high, low, range;
        //High--下一个编码区间的上限,Low--下一个编码区间的下限;
        //high--中间变量,用来计算下一个编码区间的上限;
        //low--中间变量,用来计算下一个编码区间的下限;
        //range--上一个被编码区间长度
        int i, j = 0;
        for (i = 0; i<number; i++)
        {
            if (str[0] == c[i]) break; //编码第一个字符
        }
        while (j<i)
        {
            Low += p[j++]; //寻找该字符的概率区间下限
        }
        range = p[j]; //得到该字符的概率长度
        High = Low + range; //得到该字符概率区间上限
        for (i = 1; i<size; i++) //开始编码第二个字符
        {
            for (j = 0; j<number; j++) //寻找该字符在c数组中的位置
            {
                if (str[i] == c[j])
                {
                    if (j == 0) //若该字符在c数组中的第一个字符
                    {
                        low = Low; //此时该字符的概率区间下限刚好为零 
                        high = Low + p[j] * range;
                        High = high;
                        range *= p[j]; //求出该字符的编码区间长度
                    }
                    else //若该编码字符不是c数组中的第一个 
                    {
                        float proba_next = 0.0;
                        for (int k = 0; k <= j - 1; k++)
                            proba_next += p[k]; //再次寻找字符的概率区间下限
                        low = Low + range*proba_next; //编码区间下限 
                        high = Low + range*(proba_next + p[j]);//编码区间上限
                        Low = low; //编码区间下限 
                        High = high; //编码区间上限 
                        range *= p[j]; //编码区间长度
                    }
                }
                else continue; //i++,编码下一个字符 
            }
        }
        cout << endl;
        cout << "输入字符串的编码为:" << Low << endl;
        return Low;
    }
    //译码函数
    void yma(string str, char c[], long double p[], int number, int size, long double input)
    {
        vector<char> v; //定义char类型向量v
        long double temp; //中间变量
        long double sum[N]; //存储不重复字符概率区间的下限
        sum[0] = 0.0; //数组第一个元素为0
        for (int i = 1; i<number + 1; i++) //计算数组各元素的值
        {
            sum[i] = sum[i - 1] + p[i - 1];
        }
        for (int j = 0; j<size; j++)
        {
            for (int k = 0; k<number; k++)
            {
                //确定被编码字符的下限属于【0,1】之间的哪一段 
                if ((input>sum[k]) && (input<sum[k + 1])) //发现在哪就将属于该段的字符压入向量v
                {
                    v.push_back(str[j]);
                    temp = (input - sum[k]) / (sum[k + 1] - sum[k]);//计算下一个被编码字符的下限 
                    input = temp;
                    break;
                }
                else
                    continue;
            }
        }
        cout << endl;
        cout << "译码输出为:"; //将译码结果输出
        for (int m = 0; m<v.size(); m++)
        {
            cout << v[m];
        }
        cout << endl;
    }

    第四章:LZ编码的实现之LZ-78编码

    一. LZ-78编码原理

    经过查找资料,LZ编码并不是一种编码,而是一组编码,由LZ-77和LZ-78演变而来有很多种变形。所以这里我只选取了一种比较简单的算法LZ-78算法。
    LZ-78编码算法是一种分段编码算法。算法的压缩过程非常简单。在压缩时维护一个动态词典Dictionary,其包括了历史字符串的index与内容。设信源符号集 A=a0,a1,a2...aq1 共q个字符,设输入信源序列为

    S1S2...Sn

    编码就是将此序列分成不同的X段。分段的原则是:
    1. 先取第一个符号作为第一段,然后再继续分段
    2. 若出现有与前面相同符号时,就在添加进跟随后面的一个符号一起组成一个段,以使与前面的段不同。
    3. 尽可能取最少个连通着的信源符号,并保证隔断都不相同。直至信源符号徐立结束。
    这样,不同的段内的信源符号可看成一短语,可得不同段所对应的短语字典表。若编成二元码,段号用二进制表示,段号所需码长为 l=logX(n) ,X(n)是段号数。

    二. LZ-78编码过程

    LZ-78编码在压缩时维护一个动态词典Dictionary,其包括了历史字符串的index与内容;压缩情况分为三种:
    1. 若当前字符c未出现在词典中,则编码为(0, c);
    2. 若当前字符c出现在词典中,则与词典做最长匹配,然后编码为(prefixIndex,lastChar),其中,prefixIndex为最长匹配的前缀字符串,lastChar为最长匹配后的第一个字符;
    3. 为对最后一个字符的特殊处理,编码为(prefixIndex,)
    举例
    以字符串“ABBCBCABABCAABCAAB”压缩编码构造字典的过程如下
    LZ-78编码
    1. A 不在字典中; 插入A
    2. B不在字典中; 插入B
    3. B 在字典中.
    BC 不在字典中; 插入BC
    4. B在字典中.
    BC在字典中.
    BCA不在字典中.;插入BCA
    5. B在字典中.
    BA不在字典中; 插入BA.
    6. B在字典中.
    BC在字典中.
    BCA在字典中.
    BCAA不在字典中;插入BCAA
    7. B在字典中.
    BC在字典中.
    BCA在字典中.
    BCAA在字典中.
    BCAAB 不在字典中; 插入BCAAB.

    三. LZ-78编码编程实现和性能分析

    LZ-78算法我构建了一个LZ78类。类的定义如下

    class LZ78
    {
    public:
        struct Dictionary
        {
            unsigned int Index;
            int preIndex;
            unsigned char lastChar;
            vector<unsigned char> stringInDic;
        };
    public:
        struct OutData
        {
            unsigned int preIndex;
            unsigned char lastChar;
        };
    public:
        string fileAddress;
        LZ78();   //构造函数
        void open(string);
        void Press();
        void Decode(string sourcefile, string dstfile);
    private:
        bool IfStringInDic(vector<Dictionary> CurrentString, vector<unsigned char> DataDic, unsigned int &Index);
    private:
        vector<unsigned char> FindPreString(vector<Dictionary> DataDic, unsigned int);
    };

    核心属性
    1. struct Dictionary: 存储字典信息
    2. struct OutData: 存储输出信息即上面所提到的二元组(preIndex, lastChar);
    3. string fileAddress: 需要压缩的文件的路径名称
    核心函数:
    1. void open(string address) : 打开待压缩文件
    2. void Press(): 压缩文件操作
    3. void Decode(string sourcefile, string dstfile): 解码操作
    正式操作见下面主函数:
    主函数:

    int main()
    {
        LZ78 haha;
        clock_t start, end;
        start = clock();
        haha.open("./KongFu.jpg");  //打开文件
        haha.Press();   //压缩文件
        end = clock();
        cout << "压缩文件用时:" << endl << endl;
        cout << double((end - start) / CLOCKS_PER_SEC) << "/s" << endl << endl;
        start = clock();
        LZ78 nothaha;
        nothaha.Decode("./KongFu.jpg.lz", "KongFuout.jpg");
        cout << "解压用时:" << endl << endl;
        cout << double((start - end) / CLOCKS_PER_SEC) << "/s" << endl << endl;
        getchar();
    }

    文件压缩步骤
    第一步:建立haha对象为LZ78类型
    第二步:打开待压缩的文件
    第三步:压缩文件
    第四部:压缩结束
    文件解压步骤
    第一步:建立nothaha对象为LZ78类型
    第二步:解压文件
    第三步:解压结束
    LZ-78编码的性能测试见下表
    表4.1 LZ-78编码性能测试

    原始文件890Bytes(文本)46.7kb(图像)7.82M(视频)
    压缩文件3133Bytes47.9kb7.81M
    压缩率1.291.02599.8%
    压缩用时6/s20/s/
    解码用时0/s0/s/

    看到自己程序跑的结果自己都想笑,这也太慢了点了,有时候想安慰一下自己,可能是C++读取文件的API很耗时,要想速度快,有朝一日自己写读取文件的API,励志。
    最后附上LZ-78程序的C++源代码

    LZ78.h

    #include <iostream>
    #include <fstream>
    #include <vector>
    using namespace std;
    class LZ78
    {
    public:
        struct Dictionary
        {
            unsigned int Index;
            int preIndex;
            unsigned char lastChar;
            vector<unsigned char> stringInDic;
        };
    public:
        struct OutData
        {
            unsigned int preIndex;
            unsigned char lastChar;
        };
    public:
        string fileAddress;
        LZ78();   //构造函数
        void open(string);
        void Press();
        void Decode(string sourcefile, string dstfile);
    private:
        bool IfStringInDic(vector<Dictionary> CurrentString, vector<unsigned char> DataDic, unsigned int &Index);
    private:
        vector<unsigned char> FindPreString(vector<Dictionary> DataDic, unsigned int);
    };
    
    LZ78::LZ78()
    {
    
    }
    void LZ78::open(string input)
    {
        fileAddress = input;
    }
    
    void LZ78::Press()
    {
        ifstream read;
        read.open(fileAddress, ios::in|ios::binary);
        if (!read )
        {
            cout << "文件读取错误" << endl << endl;
            return;
        }
        ofstream write;
        write.open(fileAddress + ".lz", ios::out|ios::binary);
        if (!write)
        {
            cout << "输出文件不能建立(*.lz)" << endl << endl;
        }
    
        unsigned char *firstchar = new unsigned char;
        read.read((char*)firstchar, sizeof(unsigned char));
        vector<Dictionary> DataDic;    //建立字典
        while (!read.eof())
        {
    
            if (DataDic.size() == 0)
            {
                Dictionary firstDic;
                OutData *firstout = new OutData;
                firstDic.Index = 1;
                firstDic.preIndex = 0;
                firstDic.lastChar = *firstchar;
                firstDic.stringInDic.push_back(*firstchar);
                DataDic.push_back(firstDic);
                firstout->lastChar = *firstchar;
                firstout->preIndex = 0;
                write.write((char*)firstout, sizeof(OutData));
            }
            else
            {
                unsigned char *now = new unsigned char; //用于读取的字符
                unsigned char *reallast = new unsigned char;
                vector<unsigned char> CurrentString;
                unsigned int index = 0;  //字符串存在在字典中的位置, 初始设为0
                Dictionary currentInfo;   //存储当前的单词到字典中
                OutData *currentOutdata = new OutData;  //存储当前编码信息,一会压缩进如压缩文件。
    
                int EOFflag = 0;
                do
                {
                    read.read((char*)now, sizeof(unsigned char));
                    if (read.eof())
                    {
                        EOFflag = 1;  //标记是否到文件的结尾
                        break;
                    }
                    else
                    {
                        CurrentString.push_back(*now);
                    }
                } 
                while (IfStringInDic(DataDic, CurrentString, index));
    
    
                if (EOFflag == 1)
                {
                    if (CurrentString.size() == 0)
                    {
                        break;  //如果当前字符串中没有字符,直接跳出循环
                    }
                    else
                    {     //如果当前字符串中有字符,对这段字符进行压缩。
                        *reallast = CurrentString[CurrentString.size() - 1];
                        CurrentString.erase(CurrentString.end() - 1);
                        IfStringInDic(DataDic, CurrentString, index);
    
                    }
    
                }
                else
                {
                    *reallast = *now;
                }
                currentInfo.Index = DataDic.size() + 1;
                currentInfo.lastChar = *reallast;
                currentInfo.preIndex = index;
                currentInfo.stringInDic = CurrentString;
                DataDic.push_back(currentInfo);
    
                currentOutdata->lastChar = *reallast;
                currentOutdata->preIndex = index;
                write.write((char*)currentOutdata, sizeof(OutData));
    
            }
    
        }
    
        read.close();
        write.close();
    }
    
    bool LZ78::IfStringInDic(vector<Dictionary> DataDic, vector<unsigned char> CurrentString, unsigned int &Index)
    {
        int flag = 0;
        for (int i = 0; i < DataDic.size(); i++)
        {
            if (CurrentString == DataDic[i].stringInDic)
            {
                Index = DataDic[i].Index;
                flag = 1;
                return true;
            }
    
        }
        if (flag == 0)
        {
            return false;
        }
    }
    
    
    void LZ78::Decode(string sourcefile, string dstfile)
    {
        ifstream readfile;
        ofstream putfile;
        readfile.open(sourcefile, ios::in | ios::binary);
        putfile.open(dstfile, ios::out | ios::binary);
        OutData *getdata = new OutData;
        readfile.read((char*)getdata, sizeof(OutData));
        vector<Dictionary> DataDic;    //建立字典
        Dictionary *spacefirst = new Dictionary;
        spacefirst->Index = 0;
        spacefirst->lastChar = '0';
        spacefirst->preIndex = 0;
        //spacefirst->stringInDic
        DataDic.push_back(*spacefirst);
        while (!readfile.eof())
        {
            Dictionary *now = new Dictionary;
            now->lastChar = getdata->lastChar;
            now->Index = DataDic.size();
            now->preIndex = getdata->preIndex;
            vector<unsigned char> preString;  //存储前一个的字符串
            if (now->preIndex != 0)
            { //如果preIndex等于0那么此字符是新出现的字符,否则在前面字典中找
                preString = FindPreString(DataDic, now->preIndex);
            }
            preString.push_back(now->lastChar);  
            now->stringInDic = preString;  //获取此单词的字符串。
            DataDic.push_back(*now);
            for (int i = 0; i < preString.size(); i++)
            {
                putfile.write((char*)&preString[i], sizeof(unsigned char));
            }
            readfile.read((char*)getdata, sizeof(OutData));
    
        }
        readfile.close();
        putfile.close();
    }
    
    vector<unsigned char>  LZ78::FindPreString(vector<Dictionary> DataDic, unsigned int preindex)
    {
        if (DataDic.size() < 1)
        {
            cout << "不能找到前一个字符串" << endl;
        }
        else
        {
            for (int i = 0; i < DataDic.size(); i++)
            {
                if (preindex == DataDic[i].Index)
                {
                    return DataDic[i].stringInDic;
                }
            }
        }
    }

    LZ-78Main.cpp

    #include "LZ78.h"
    #include <string>
    #include <time.h>
    int main()
    {
        LZ78 haha;
        clock_t start, end;
        start = clock();
        haha.open("./KongFu.jpg");  //打开文件
        haha.Press();   //压缩文件
        end = clock();
        cout << "压缩文件用时:" << endl << endl;
        cout << double((end - start) / CLOCKS_PER_SEC) << "/s" << endl << endl;
        start = clock();
        LZ78 nothaha;
        nothaha.Decode("./KongFu.jpg.lz", "KongFuout.jpg");
        cout << "解压用时:" << endl << endl;
        cout << double((start - end) / CLOCKS_PER_SEC) << "/s" << endl << endl;
        getchar();
    }

    总结

    经过此次试验真的是收获了很多,首先是对各种编码的熟悉,从Huffman编码、Shannon Fano码、算数编码到LZ编码家族,了解了Zip,winrar等压缩软件的压缩原理,以及压缩算法从兴起到应用,里面还有一些版权纠纷的故事(LZW版权问题)。到现在的操作系统使用的压缩软件的情况,Windows主要的软件是winrar和zip, linux系统下主要是.gz和gzip软件。其原理都是基于DELLATE算法的。DELLATE算法是以Huffman编码和LZW编码为核心的。另一方面,从信息论角度细致的学习了各种编码的编码原理和译码方式,这些收获相信在今后的学习中都会有用的。这次实验不仅锻炼了编程能力,而且学习到很多编码领域的新知识。

    参考文献
    《信息论与编码》傅祖芸、赵建中 电子工业出版社
    C++实现Huffman文件编码和解码:http://www.cnblogs.com/matrix-r/p/3354887.html
    zip压缩原理 http://blog.jobbole.com/76676/
    Huffman对文件编码和解码http://blog.csdn.net/computer_liuyun/article/details/41446773
    huffman编码原理与实现:http://blog.csdn.net/abcjennifer/article/details/8020695
    二进制和ASCII编码: http://blog.csdn.net/sxhelijian/article/details/29594687
    压缩编码的历史:http://blog.csdn.net/kimylrong/article/details/39405981
    Lz78算法:http://www.cnblogs.com/aeexiaoqiang/p/6529375.html
    算数编码: http://blog.csdn.net/adam_tu/article/details/7696455

    展开全文
  • 信息传输技术

    2019-11-09 16:05:08
    信源和信宿 信源按所发出的信息在时间域内的表现形式可划分为离散信源和连续信源。 离散信源通常是字符型或者数据型信源,因为字母、数字或者文字都是在时间轴上分隔开的信息。而连续信源是指在时间轴上发出连续...
  • 当然即使如此,这两种简单信道的应用也包罗万象,包括卫星广播(卫星单一发射,多个地面接收)、基站多址接入(多终端发射,单基站接收)等等。 多址信道(多个发射端一个接收端)和广播信道(一个发射端多个接收...
  • 实验目的1. 实现压缩编码算法——Huffman编码 2. 实现压缩编码算法——Shannon Fano编码 3. 实现压缩编码算法——LZ编码 4. 实现压缩编码算法——算数编码 ...[信源编码源代码](https://github.com/PiggyGa
  • 高铁广播系统

    2021-06-29 06:23:30
    高铁自动广播系统是消防紧急广播与业务广播合二为一的广播系统,在平时作为车站业务广播使用,在有火灾报警信号时,切换为消防广播使用。在业务广播时,主要由自动广播及人工广播组成。高铁公共广播系统的车次...
  • 从0-1建设企业软件版本的唯一可信源 电信IT规模上云之数字化技术底座建设实践 DevSecOps安全实践分享 DevOps时代运维知识图谱和职业发展 DevOps进程中自动化运维平台建设成果 打造证券数字化转型的基础核心竞争力-...
  • 针对数字直放回波抵消技术中自适应滤波法在多径回波信道条件下不能完全消除次径回波的问题,提出了基于盲信号分离的直放回波抵消方法。首先对施主天线接收的混合信号进行相空间重构,使观测信号的数目大于等于...
  • 、5G室内分布系统必须达到4路以上射频发射通道(即:信源侧至少能满足4T) ,才能使 5G 手机体验到四通道下载速率。但是,在一些存量室内分布系统中, 目前的硬件部署只满 足2路射频发射通道(即:信源侧只能满足...
  • 请求伪造

    千次阅读 2016-10-28 01:43:24
    请求伪造
  • 火星探测极远的通信距离以及行星遮挡,使得探测车与地面的通信需要构建火星临近...仿真验证了新方案与已有的分布式喷泉方案相比,降低了约50%的信源编码开销,并通过复杂度与译码冗余的折衷,达到了99.9%的译码成功率。
  • 基于此原理,在中心利用10 GHz的本振射频信号,通过调节两个调制器的相位差和强度调制器的偏置电压产生40 GHz光载毫米波信号,2.5 Gb/s的基带数据信号直接调制在光载毫米波上,经过20 km标准单模光纤传输至基站。...
  • 8.5 IP源选路选项

    2021-08-10 06:45:07
    选路(source routing)的思想是由发送者指定路由。它可以采用以下两种形式:• 严格的源路由选择。发送端指明IP数据报所必须采用的确切路由。如果一个路由器发现源路由所指定的下一个路由器不在其直接连接的网络...
  • 在考虑WCDMA网络室内覆盖建设策略时,从信号源角度分析,需要根据场景的无线环境和工程条件灵活选择信源,同时要综合权衡系统容量、频率资源、预期收益、投入成本、预期效果等多方面因素。从容量角度考虑。根据所...
  • 信息通信技术

    千次阅读 多人点赞 2022-02-25 10:22:34
    (1)通信的三要素:①信源->②信道->③信宿 ①、信源:发送信息的设备 ②、信道:供信号传播的通道。信道包括模拟信道和数字信道。(也有有线、无线之分) ③、信宿:接受信息的设备 (2)举例:...
  • B链接:https://www.bilibili.com/video/BV1c4411d7jb?p=1 第1章 计算机概述 1. 各种网络 网络(Network)由若干结点Node和连接这些结点的链路Link组成 多个网络还可以通过路由器互连起来,这样就构成了一个覆盖...
  • 8.5 IP源选路选项 通常I P路由是动态的,即每个路由器都要判断数据报下面该转发到哪个路由器。应用程序对此不进行控制,而且通常也并不关心路由。它采用类似 Tr a c e r o u t e程序的工具来发现实际的路由。 源...
  • B团队是目前少数在生产环境中部署QUIC的视频平台,收益明显。在面对未来网络基础设施升级的背景下,如何让视频传输更流畅、稳定是各视频服务平台必须面临的挑战。LiveVi...
  • 基带信号:来自信源的信号(源系统发送的比特流)。 5.调制 基带调制:对基带信号的波形进行变换,使之适应信道。调制后的信号仍是基带信号。基带调制的过程叫做编码。 带通调制:使用载波进行调制,把基带信号的频率...
  • 码分多址CDMA

    千次阅读 2021-03-20 19:43:59
    码分复用,CDM,CDMA 最近复习《计算机网络》,遇见一些比较困难的...比如S要发送比特1,S被指派的码片序列是00011011,原来发送的比特1改为发送码片序列00011011,发送比特0改为发送11100100(其反码),原来发送
  • 源系统包括源点(或源信源)和发送器,目的系统包括接收器和终点(或目的、信宿)。 3、通信的目的是传送消息。话音、文字、图像、视频等都是消息。数据是运送消息的实体。信号则是数据的电器或电磁的表现。 4...
  • 三.计算机网络之物理层

    千次阅读 2021-12-04 20:18:07
    信源(发送方的电脑):通过信源输入信息 发送器():信源发送的数据经过发送器调制后,变成模拟信号。 信源和发送器共同组成源系统 传输系统:指的就是公用电话网即广域网 接收器: 信宿:目的主机 接收器和信宿构成...
  • 源点又称为源,或信源。 (2)发送器:源点生成的数字比特流要通过发送器编码后才能在传输系统中进行传输。典型的发送器就是调制器。现在很多计算机使用内置的调制解调器。 目的系统一般包括以下两个部分: (1)...
  • 然后为了从系统中获取单个文件(而不是磁盘映像),我编写了一个自定义 KERMIT-80,以使我能够将文件从 S-100 设备中批量传输到我的 Linux 工作。”人们总是对未知充满好奇,无论是无法回到的回去还是不能预知的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,024
精华内容 1,209
关键字:

信源站