自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(9)
  • 资源 (6)
  • 收藏
  • 关注

转载 自行研制四轴交流

转发:www.eopn.net(蓝蜻蜓网)从开始做四轴到现在,已经累计使用了三个月的时间,从开始的尝试用四元数法进行姿态检测,到接着使用的卡尔曼滤波算法,我们走过了很多弯路,我在从上周开始了对德国人四轴代码的研究和移植,发现德国人的代码的确有他的独到之处,改变了很多我对模型的想法,因为本人是第一次尝试着制作模型,因此感觉很多想法还是比较简单。经过了一周的时间,我将德国人的代码翻译并移植到了我目

2013-04-23 16:30:03 978

原创 指纹识别的原理和方法

<br />指纹识别的原理和方法<br />一.概述 <br />    指纹识别技术主要涉及四个功能:读取指纹图象、提取特征、保存数据和比对。 <br />    在一开始,通过指纹读取设备读取到人体指纹的图象,取到指纹图象之后,要对原始图象进行初步的处理,使之更清晰。 <br />    接下来,指纹辨识软件建立指纹的数字表示--特征数据,一种单方向的转换,可以从指纹转换成特征数据但不能从特征数据转换成为指纹,而两枚不同的指纹不会产生相同的特征数据。软件从指纹上找到被称为"节点"(minutiae)的数

2010-12-04 15:45:00 11450

原创 Qbasic练习题

一、填空  10分      1.      由0、1的不同组合所形成的可以被计算机直接识别的二进制代码的集合称为__________。      2.      用高级语言编写的程序叫做高级语言_________。      3.      所谓__________是人们为解决具体问题所采取的方法和步骤。      4.      结构化设计方法规定的三种具有良好特性的基本结构,包括__________、__________和循环结构。      二、在下列QBASIC常数中,请在写法正确的后面打“√”,

2010-12-04 15:43:00 2747

原创 C语言习题集

'=======================================================================================================以下文章送给正在学习C语言的网友,希望可以帮到你们。在这里谢谢你们的支持。  祝:你们学习愉快我的和讯www.eopn.net蓝蜻蜓生活网'==================

2010-12-04 15:41:00 7841 1

转载 梵塔问题

这道谜题是众所周知的梵塔问题(①译者注:梵塔问题源于有关“世界末日”的古老传说:在世界中心贝那勒斯(印度北部的佛教圣地)的圣庙里,安放着一块黄铜板,板上插着三根宝针,细如韭叶,高约腕尺.梵天在创造世界的时候,在其中的一根针上,从下到上串上由大到小的64片金片.这就是所谓梵塔.当时梵天授言:不论黑夜白天,都要有一个值班的僧侣,按照梵天不渝的法则,把这些金片在三根针上移来移去,一次只能移一片,并且要求不管在哪根针上,小片永远在大片上面.当所有的64片,都从梵天创造世界时所放的那根针,移到另外一根针上时,世界就将

2010-12-04 15:38:00 2969

原创 vb 如何使用动态创建xml文件

<br />以下是自己以前写的vb 读写操作xml 完正的类模块,<br />我的和讯http://hexun.com/haoguoying<br />我的百度http://hi.baidu.com/haoguoying/home<br /> <br />Option Explicit<br />Public name As String       '目录名称<br />Public val As String        '只有在是叶子的时候才有用<br />Private Ctree() As cl

2010-12-04 15:37:00 1546

原创 半透明窗体

半透明窗体(窗体对鼠标点击有反应): Option Explicit Transparancy APIs Private Declare Function SetLayeredWindowAttributes Lib "user32" (ByVal hWnd As Long, ByVal crKey As Long, ByVal bAlpha As Byte, ByVal dwFlags As

2009-07-08 09:00:00 472

原创 VB编程中的Unicode vs Ansi

Unicode vs Ansi Visual Basic 32-bit 版本的字串处理采用 Unicode,也就是说字串在 VB 内部是以 Unicode 的格式来存放。 何谓 Unicode?简单的说,就是每一个字元都是以 2-byte 的型式表示,而每个「实 体字元」就是一个「字元」。因此, Len("大家好") Len("abc") 所传回的值都是 3,因为「大」和「a」都是一个字元。

2008-03-25 08:34:00 533

原创 MD5加密算法原理

MD5加密算法原理的Java Bean实现MD5简介 http://haoguoying.blog.hexun.com/14081699_d.htmlMD5的全称是Message-Digest Algorithm 5,在90年代初由MIT的计算机科学实验室和RSA Data Security Inc发明,经MD2、MD3和MD4发展而来。 Message-Digest泛指字节串(Messa

2008-01-27 15:16:00 1573

管vb开发的 理你所收集的源程序

老外写的《理你所收集的源程序》 很值得初学都学习 老鸟也可以拿去看看。自我感觉不错,推荐给在家。

2011-04-04

Modbus通信协议

摘 要:工业控制已从单机控制走向集中监控、集散控制,如今已进入网络时代,工业控制器连网也为网络管理提供了方便。Modbus就是工业控制器的网络协议中的一种。 关键词:Modbus协议;串行通信;LRC校验;CRC校验;RS-232C 一、Modbus 协议简介 Modbus 协议是应用于电子控制器上的一种通用语言。通过此协议,控制器相互之间、控制器经由网络(例如以太网)和其它设备之间可以通信。它已经成为一通用工业标准。有了它,不同厂商生产的控制设备可以连成工业网络,进行集中监控。 此协议定义了一个控制器能认识使用的消息结构,而不管它们是经过何种网络进行通信的。它描述了一控制器请求访问其它设备的过程,如果回应来自其它设备的请求,以及怎样侦测错误并记录。它制定了消息域格局和内容的公共格式。 当在一Modbus网络上通信时,此协议决定了每个控制器须要知道它们的设备地址,识别按地址发来的消息,决定要产生何种行动。如果需要回应,控制器将生成反馈信息并用Modbus协议发出。在其它网络上,包含了Modbus协议的消息转换为在此网络上使用的帧或包结构。这种转换也扩展了根据具体的网络解决节地址、路由路径及错误检测的方法。

2011-04-04

P2P视频技术源码(VC)

1. 架构说明 目前的协议有如下一些特点: 1) 客户向服务器发送请求, 每个请求的长度不定. 请求的长度在第一个INT中指定. 2) 每个服务器通常会向多种客户提供服务, 例如, TS要同时向CP, NP提供服务, CP要向NP和其他CP提供服务, 同时还是其他CP, TS, SP的客户. 3) 每个服务器为客户服务时, 通常是长期的, 会涉及多次请求-应答的来回. 这样的结构, 主要是为了能够支持大量并发客户连接而设计的. 在具有大量并发客户 连接时, 无论采用线程还是进程, 都无法进行有效的服务, 因此必须采用select 轮询方式. 2. 基本数据结构说明 对于每个客户端, 需要保存该客户端相应的一些信息. 目前的CPnew.c, SPnew.c 和TSnew.c的核心数据结构基本相同, 都由Session, SessionCluster (TSnew.c中) 或者 ServerDesc (CPnew.c和SPnew.c)构成. 其中, Session是每个客户端相关的数据, SessionCluster(或者是ServerDesc)是 有关每种服务的信息, 其中有一个指向该服务相关的各个Session的指针. Session 这一数据结构不是在有客户请求时动态分配的, 而是在最开始初始化时就已经分配 好的, 当有新客户请求到来时, 服务器搜索这一预先分配好的这些Session, 发现其中 有空闲则使用, 如果没有空闲就报告错误. 对于TS和CP(SP)来说, 最大的区别是TS使用UDP协议, 而CP和SP则使用TCP协议, 二者的 不同在于: 1) 对于TCP协议的客户端, 由于每个客户端都使用不同的socket, 因此select之后 只需要看各个客户端的fd_set是否置位就可以了, 而对于UDP客户端, 找到相应的 客户端需要进行一次查找过程. TS使用了一些措施来减轻查找所带来的开销. 2) TCP协议中, 发来得数据是流形式的, 因此需要进行消息分块, 有可能两个消息 在一次read中读完, 也有可能一个消息需要读很多次, 这两种情况都需要考虑, 因此 每个Session中都有一个buf, rstart, rlen, 用来存储读来但还没有处理的消息, 同样, 写的过程中也需要考虑写的时候有可能没有一次写完, 因此也需要每个Session中 保留wbuf, wstart, wlen三项. UDP中则不同, 在协议实现中假设每个UDP数据包中 所包含的消息都是完整的, 因此没有这几项. SessionCluster(或者是ServerDesc)来说, 描述了一个服务, 这个服务由这样几个 主要的部分构成 1) sock: 描述所所使用的socket 2) cur: 当前客户端的个数 3) max: 最多容纳客户端的个数 4) head: Session的头, head[0]为第一个Session, head[max-1]为最后一个session 5) init: 这一服务中每个Session需要执行的初始化操作. (函数指针) 6) process: 这一服务中消息的处理函数 7) closure: 这一服务中需要的析构函数 3. 主要结构说明 process_child: 主要函数, 这一函数主要用来 设置socks和wsocks, 对于SP和CP, 只有Session的wlen>0的时候才设置wsocks; select; 对于每个ServerDesc(或者SessionCluster), 进行process_type 在SP和CP中, 为了支持PUSHLIST操作, 在每一次循环前先要进行processJob 在CP中, 还周期进行periodCheck, 用来将过期的连结清除 在TS中, 周期进行periodLog, 用来将过期的客户连接清除 process_type: 对于每个Session, 检查是否可读. 如果可读, 检查是否有完整的消息, *(unsigned int *)(rbuf+rstart) 0, 则进行写 4. 其他重要的模块 1) 配置模块 配置模块主要由struct NamVal, read_config, free_config组成, NamVal结构中, Name是在cfg文件中的名字, ptr是指向存放的指针, type是数据的类型, 目前支持这样 几种类型 'd': 整数类型, ptr是一个整数指针 's': 字符串类型, ptr是一个指向指针的指针, (char **) 'b': 字符串buffer类型, ptr是一个char *, 使用这种类型时应当注意, 对于's'类型, read_config将为该val分配内存(malloc), 但是对于'b' 类型, ptr所指向的必须是已经 分配好的内存 两个重要的函数分别为: read_config, 参数为文件名, 一个struct NamVal *, 以及该struct NamVal的项数 free_config, 参数为和read_config相同的struct NamVal *以及项数 2) mysql 模块 mysql模块主要有MYSQL *local_mysql以及三个函数构成, 这三个函数是 init_mysql, 初始化mysql, 返回一个MYSQL *, 一般用来初始化local_mysql query_mysql, 执行一个mysql语句, 格式为query_mysql (local_mysql, "mysql语句, 其中格式和printf的格式相同, 例如delete from %s等", 所需要的值) query_mysql_select, 执行一个mysql的select语句, 与上面不同的是, 它返回一个 MYSQL_RES *. 3) network排序模块 这一模块主要由networks结构, readNETBLOCK函数, getnetwork函数, compareNet函数 构成, 其中, readNETBLOCK用来读入network配置文件, 初始化全局变量NETBLOCKS, NETBLOCKS是一个 networks结构数组, 有MAX_NET项. getnetowrk用来查找和一个IP地址最接近的netblock compareNet是在qsort中用到的一个函数, 对找到的NPPeer进行排序, 让同一个网络 中的NPPeer排在前面. 4) 图管理 在目前的CP, SP, NP中, CP可以同时加入多个频道, 而NP也可以有多个资源, 为了描述 这种结构, 引入了图的概念. 每个边(Edge)存储了指向NP的指针, 指向Channel的指针, 在TS中还需要存储这一Session在这一Channel中的各个Interval. 每个Channel通过Edge 中的cnext串成一个链表, 这个链表的头是Channel结构中的PeerHead, 而每个Session 通过Edge中的enext也串成一个链表, 这个链表的头是Session结构中的header. 相关的函数有: newEdge: 新添一个边, 参数为Channel *, Session *, 对于TS还需要一个ChannelInfo来 初始化Edge中的信息 delEdge: 删除一个边, 参数为Edge * 5) Channel模块 Channel模块的功能主要是: TS中用来处理NEED_PEERS, SP中还需要保存和查找频道数据, 频道都使用图结构进行管理. 频道的搜索为了效率方面的因素, 采用了Hash进行搜索, ChannelHash中使用的是字符串 hash, 如hash_str所示. TS中的Channel相对较为简单, SP和CP中Channel还需要管理Channel相关的数据. 这些 数据以文件的形式存在硬盘上/var/tmp/目录下, 文件名随机生成, 对于每一块的相关信息, 由BlockData来保存, BlockData中的firstsampl, message_size, message_id, offset分别 存储了firstsample信息, 快的长度, 块的id, 以及在文件中的offset. SP和CP的处理有所不同, 对于CP, 块是以hash的方式来存放的, 例如, 块的ID为1000, 而 max_queue为100, 则存储位置为1000%100=0. 对于SP, 如果资源是一个CS发来的频道, 则是一个循环队列, 每一块按照次序分别存放在相应位置, 如果到了队列尾部, 就再从 队列头开始. 如果资源是文件, 就不保存BlockData信息, 直接根据blockID到原文件定位. 涉及Channel的函数有很多, 如locate_by_id, locate_order_by_id, newChannel, freeChannel, saveBlock等. 6) Berkeley DB模块 这只在SP中涉及, 主要是打开DB文件, 查询某个md5的位置. 主要涉及到DB* MediaDB, openDB, openMedia这两个函数 openDB: 参数为DB文件的名 openMedia: 参数为md5和一个整数指针, 返回FILE *以及该文件的长度, 在整数指针中 7) Job模块 Job模块用在CP和SP中, 用来处理PUSHLIST, PUSHLIST消息可以重新设置Job的列表, 也可以添加Job或者是删除Job. 涉及到job.c中的函数和JobDes结构. JobDes结构 中一个Session *, 一个Channel *用于标识该Job所属的Session和Channel, num表示 所需要下载的BlockID数, job是一个指向整数的指针, mask也是一个指向整数的指针, job 是需要下载的BlockID, 如果mask为0,则需要进行下载, 如果为1, 则不需要. addJob: 添加job的时候, 不检查该Job是否已经在列表中, 直接生成一个Job然后 添加到链表中. deleteJob: 删除Job时, 检查所有Job列表中的具有相同Session和Channel的Job, 然后将需要删除的blockID的相应mask设置为1. processJob: 对于每个job, 从cur开始, 利用process_P2P_REQUEST_real来传输 第一个mask为0的块, 如果都为1, 就删除这个job. freeJob: 删除某个JobDes. freeJobList: 删除某个Session的所有JobDes, 通常用于该Session退出时使用. 8) Interval模块 Interval模块用在TS中, 用来表示NP上面所有的快区间, 目前块区间由一个开始 字段和一个长度字段来标识. 对于Interval的主要操作是merge和delete, merge 是将原有的Interval和新的Interval列表合在一齐, 而delete则是从原有的当中 去掉新的. merge: 算法如下, 使用了缓冲Interval列表tmp. if (old < new[j]) tmp[k] = old; else tmp[k] = new[j]; 然后再看old和new中哪些能够可以和tmp[k]合并 delete: 较为复杂一些, 考虑下面几种情况 old的开始比new[j]的结束大 old的结束在new[j]的开始前 old和new[j]有共同部分, 而且 old含在new[j] 中 new[j]含在old中 互不包含, new[j] 在前 互不包含, old 在前 5. 一些快速算法 1) 在使用UDP的TS中, 在客户初次登录时, 需要查找空闲的Session, 此外, 客户有可能 会重复发送LOGIN消息, 这时需要检查这一客户端是否已经在Session列表中, 第三, 当 客户端发送消息时, 需要找到相应的Session. 为了避免这些查询, 分别使用了如下方法. 首先, 建立一个Hash表, 开始的时候所有空闲Session都串到Hash[0]处, 每当来一个 新的客户端时,从Hash[0]中取出Session, 链到相应的hashid上. 为此, hash所得的值 不能为0, 如果为0, 就返回最大的可能hashid. 根据来源端口和IP地址查询Session也使用这一Hash表. 客户端发送消息时, 使用了用于验证的7个字节中的前3字节, 用这3字节来标识Session 的下标, 这样就避免了查询开销. 2) 使用maxid来减少搜索次数. 在TCP中没有使用Hash, 使用了maxid这一项, 用来记录Session中最大的id, 由于在Session 初始化的时候, 是查找ID最小的空闲Session, 因此可以认为Session是比较紧凑的, 由于SP和CP支持的客户端要比TS少得多, 因此这样的处理是可以接受的. 在客户退出的时候, 有可能需要更新maxid, 这一更新是由Clientclosure来完成的, Clientclosure更新maxid, 然后再调用相应的析构函数. 3) 长期idle的连接的超时处理. 由于超时处理需要遍历整个列表, 为了节约系统资源, IDLE时间比较长, 此外, 一般还需要定期报告系统统计数字, 因此需要及时性. 为此, 一般periodLog或者periodCheck都判断是执行这两者中的哪一种操作. 4) 查询CPPeer时, 考虑到目前只支持GCP, 因此直接采用了GCPCHOICE,设置为当前 负载最小的GCP, 在GCP报告或者是GCP登录, 退出的时候更新. 6. 消息处理 1) TS消息处理 NP2TS_LOGIN: NP向TS登录, 按照来源IP地址和所报告的npport进行hash, 如果距离上次 发送NP2TS_LOGIN消息的时间小于SILENCE_TIME, 则直接返回, 否则发送WELCOME消息. NP2TS_REPORT: 报告Interval信息, 如果refresh为true, 则重置, 否则则先增加后删除. NP2TS_NEED_PEERS: 查询Peer信息, 使用findCPPeer寻找合适的CP, 使用findNPPeers 寻找合适的NP. NP寻找时, 找到结果后按照networks来排序, 保证在同一个网络中的 排在前面. NP2TS_LOGOUT: 退出 NP2TS_RES_LIST:发送当前NP的所有RESOURCE, 使用addSession来进行处理, 如果还没有这 条边, 就添加 NP2TS_REQ_RES: 添加RES, 并返回Peers NP2TS_DEL_RES: 删除RES CP2TS_REGISTER: 登录, CP向TS登录, 按照来源IP地址和所报告的npport进行hash, 如果距离上次发送CP2TS_REGISTER⒌氖奔湫∮赟ILENCE_TIME, 则直接返回, 否则发送 WELCOME消息. CP2TS_UPDATE: 报告CP负载 CP2TS_NEED_PEERS: ECP查询用, 目前尚未使用 2) SP消息处理 P2P_HELLO: 加入某个频道, 如果频道存在 如果是个Media文件: 返回SPUPDATE, 表明这一频道的最小最大blockID 否则: 如果这一频道已经结束, 返回结束信息 如果频道不存在 如果是个Media文件: 返回SPUPDATE, 表明这一频道的最小最大blockID, 建立频道 否则: 返回一个SPUPDATE指示错误 P2P_PUSHLIST: 重置或者是增加删除任务列表. 重置时, 先删除所有的相关任务, 然后 再增加或删除. CS2SP_REGISTER: 建立频道 CS2SP_UPDATE: 更新频道信息 CS2SP_BLOCK: 发送数据块 3) CP消息处理 P2P_HELLO: 加入某个频道, 根据提供的SP地址来建立相应连接 P2P_PUSHLIST: 重置或者是增加删除任务列表 P2P_SPUPDATE: SP发来的SPUPDATE, 如果是Media文件, 则不转发给NP P2P_RESPONSE: SP发来的数据块. 此外CP还需要向TS注册. 目前只有GCP一种类型在使用.

2010-12-04

MSP430 x1xx family user's guide

好久没有上传了,MSP430用户指南,希望可以帮助正在学习的430的朋友

2010-12-04

vb 简单多页面浏览器

好久没有上传代码了,大家可以看看一个很不错了软件,在过几天给大空上传我自己写vb IE面浏览器。下面的图不是这个资源的图片(vb 简单多页面浏览器)而是我下次要上传的多功能 浏览器。 QQ:87867861 我的和讯http://hexun.com/haoguoying 我的百度http://hi.baidu.com/haoguoying/home

2010-10-24

vb 网络音乐播放器源码

如果您是第一次使用本软件,请务必仔细阅读以下说明: 软件名称:NetPlayer网络音乐播放器V1.3.05,为叙述方便,后简称'本软件'.前身是我一年前完成的NetPlayer在线排行榜播放器.当时出于自己方便听歌的目的开发,后来由于课程紧张,不完善之处一直没来得及修正.直到几天前才得以腾出时间完成.以下是本软件的基本功能简介: 1.在线实时获取国内专业试听网站的歌曲排行榜,包括热歌,老歌和新歌. 2.后台搜歌引擎共3套,sogou(搜狗),baidu(百度),以及soso(搜搜). 3.歌词引擎2套,分别来自红叶歌词网和百度. 4.写真系统包括桌面壁纸,套图,qq头像等,后台主引擎默认为sogou. 5.专辑列表功能,后台数据取自搜狗音乐大本营. 6.实时MTV查找播放功能. 7.内置国内外200+个在线电台,按地区分类. 8.听歌过程中实时获取歌手/专辑信息,该歌手的所有歌曲,以及写真. 9.智能纠错算法,共分7种,有效保证播放的成功率,以及预防某些恶意代码所致的弹出页面. 10.同步可拖定位歌词显示. 11.支持多播放列表,最大数无限制. 12.其他功能:歌曲下载到本地/将排行榜歌曲添加到播放列表/组合搜索/信息模式切换等等. 几个重要说明: a.当播放排行榜单的某一首歌曲时,后台会预存20个地址备用.如果感觉当前音效不是很好或者根本就是翻唱,可再次双击列表同一首歌,后台地址会自动切换到第二个,以此类推. b.出于兼容性考虑,新建播放列表名请使用英文字母或数字,切勿用中文. c.有关组合搜索(歌曲+歌手),即同时向服务器发送歌曲和歌手信息来进行查询,这样的好处是返回的结果更准确.但是也同时带来弊端,返回结果数可能很少.这就类似于精确查询和模糊查询的道理. d.有关强制更新榜单,了解web技术的朋友都知道cache的问题,因此如果选中此项,后台获取信息的同时会强制带一个随机参数,以避开cache优先从网站获取数据. e.有关智能纠错,强烈建议前6项务必选上!第七项自动下载歌词顾名思义用不到解释.这里重点解释下最后一项,lrc歌词校验,这个主要是通过读取lrc歌词文件内标签来判断,由于每首歌单体节奏存在差异,因此不一定能完全判断正确.不喜欢此功能可以关闭. f.有关监视窗口,这个主要是方便调试,里面显示的是后台的部分传递参数,包括当前歌曲使用的是哪一个备用地址等. g.有关歌手档案以及写真功能,播放歌曲时,如果激活这2个窗口将在线获取相应的信息,其中写真功能,点击缩略图之后可进入全屏浏览模式.在此模式下可进行设置为桌面壁纸以及幻灯片播放等操作. h.有关歌词调整,在此可对歌词进行每次提前或者延迟0.5秒操作,当调整到最佳值之后,如果想保存此offset的话一定要记得手动点击保存到歌词文件选项.为防止误操作,本软件不自动对offset值进行保存. i.有关更换歌词,如果对当前显示的歌词不满意,可手动点击此按钮,在随后出现的窗口中会出现当前歌曲的所有可下载歌词,内容与您设置的歌词引擎有关.选择其中一个,点击下载歌词即可,直到满意为止. j.有关专辑功能,激活后默认打开最新发布的专辑,具体包括精彩大碟/中文最新/欧美最新/日韩最新四种分类.点进去后可查看详情.也可手动输入歌手名,进行该歌手的所有专辑查询.所有后台数据取自搜狗. k.本软件共为您准备了3套搜歌引擎,可根据您的喜好或访问速度进行切换.由于网络的日新月异,搜歌引擎网站也可能进行改版,届时如果发生某套搜歌引擎不能正确运行,请暂时切换成其他引擎,并及时通知我. l.如果使用本软件过程中,想恢复到默认配置,请到\bin目录下删除config.ini文件,重启本软件即可. 预期下个新版本功能: 增加歌手列表功能.有时间的话会尽早做.或者您有什么好的建议告诉我. QQ:87867861

2009-03-12

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除