﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-Junky's IT Notebook-随笔分类-计算机科学,编程思想</title><link>http://www.blogjava.net/junky/category/16580.html</link><description /><language>zh-cn</language><lastBuildDate>Wed, 10 Oct 2007 08:17:54 GMT</lastBuildDate><pubDate>Wed, 10 Oct 2007 08:17:54 GMT</pubDate><ttl>60</ttl><item><title>什么是批处理?</title><link>http://www.blogjava.net/junky/archive/2007/10/10/151618.html</link><dc:creator>junky</dc:creator><author>junky</author><pubDate>Wed, 10 Oct 2007 01:41:00 GMT</pubDate><guid>http://www.blogjava.net/junky/archive/2007/10/10/151618.html</guid><wfw:comment>http://www.blogjava.net/junky/comments/151618.html</wfw:comment><comments>http://www.blogjava.net/junky/archive/2007/10/10/151618.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/junky/comments/commentRss/151618.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/junky/services/trackbacks/151618.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 批处理文件是无格式的文本文件，它包含一条或多条命令。它的文件扩展名为 .bat 或 .cmd。在命令提示下键入批处理文件的名称，或者双击该批处理文件，系统就会调用Cmd.exe按照该文件中各个命令出现的顺序来逐个运行它们。使用批处理文件（也被称为批处理程序或脚本），可以简化日常或重复性任务。当然我们的这个版本的主要内容是介绍批处理在入侵中一些实际运用，例如我们后面要提到的用批处理文件来给系统打补丁...&nbsp;&nbsp;<a href='http://www.blogjava.net/junky/archive/2007/10/10/151618.html'>阅读全文</a><img src ="http://www.blogjava.net/junky/aggbug/151618.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/junky/" target="_blank">junky</a> 2007-10-10 09:41 <a href="http://www.blogjava.net/junky/archive/2007/10/10/151618.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>同步和异步的区别集锦</title><link>http://www.blogjava.net/junky/archive/2006/12/18/88659.html</link><dc:creator>junky</dc:creator><author>junky</author><pubDate>Mon, 18 Dec 2006 15:43:00 GMT</pubDate><guid>http://www.blogjava.net/junky/archive/2006/12/18/88659.html</guid><wfw:comment>http://www.blogjava.net/junky/comments/88659.html</wfw:comment><comments>http://www.blogjava.net/junky/archive/2006/12/18/88659.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/junky/comments/commentRss/88659.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/junky/services/trackbacks/88659.html</trackback:ping><description><![CDATA[通俗版:<br /><br />举个例子：普通B/S模式（同步）AJAX技术（异步）<br />同步：提交请求-&gt;等待服务器处理-&gt;处理完毕返回 这个期间客户端浏览器不能干任何事<br />异步: 请求通过事件触发-&gt;服务器处理（这是浏览器仍然可以作其他事情）-&gt;处理完毕<br />--------------------------------------------------------------------------------------------------------------------<br />同步就是你叫我去吃饭，我听到了就和你去吃饭；如果没有听到，你就不停的叫，直到我告诉你听到了，才一起去吃饭。<br />异步就是你叫我，然后自己去吃饭，我得到消息后可能立即走，也可能等到下班才去吃饭。
<p>所以，要我请你吃饭就用同步的方法，要请我吃饭就用异步的方法，这样你可以省钱。<br />--------------------------------------------------------------------------------------------------------------------<br />举个例子 打电话时同步 发消息是异步<br /><br /><br />综述版:<br /><br />异步通信”是一种很常用的通信方式。异步通信在发送字符时，所发送的字符之间的时间间隔可以是任意的。当然，接收端必须时刻做好接收的准备（如果接收端主机的电源都没有加上，那么发送端发送字符就没有意义，因为接收端根本无法接收）。发送端可以在任意时刻开始发送字符，因此必须在每一个字符的开始和结束的地方加上标志，即加上开始位和停止位，以便使接收端能够正确地将每一个字符接收下来。异步通信的好处是通信设备简单、便宜，但传输效率较低（因为开始位和停止位的开销所占比例较大）。 <br />异步通信也可以是以帧作为发送的单位。接收端必须随时做好接收帧的准备。这是，帧的首部必须设有一些特殊的比特组合，使得接收端能够找出一帧的开始。这也称为帧定界。帧定界还包含确定帧的结束位置。这有两种方法。一种是在帧的尾部设有某种特殊的比特组合来标志帧的结束。或者在帧首部中设有帧长度的字段。需要注意的是，在异步发送帧时，并不是说发送端对帧中的每一个字符都必须加上开始位和停止位后再发送出去，而是说，发送端可以在任意时间发送一个帧，而帧与帧之间的时间间隔也可以是任意的。在一帧中的所有比特是连续发送的。发送端不需要在发送一帧之前和接收端进行协调（不需要先进行比特同步）。 每个字符开始发送的时间可以是任意的t0 0 1 1 0 1 1 0起始位结束位t每个帧开始发送的时间可以是任意的以字符为单位发送以帧为单位发送帧开始帧结束 <br />“同步通信”的通信双方必须先建立同步，即双方的时钟要调整到同一个频率。收发双方不停地发送和接收连续的同步比特流。但这时还有两种不同的同步方式。一种是使用全网同步，用一个非常精确的主时钟对全网所有结点上的时钟进行同步。另一种是使用准同步，各结点的时钟之间允许有微小的误差，然后采用其他措施实现同步传输。<br /><br /><br />串口进行通信的方式有两种：同步通信方式和异步通信方式。同步通信方式要求通信双方以相同的时钟频率进行，而且准确协调，通过共享一个单个时钟或定时脉冲源保证发送方和接收方的准确同步，效率较高；异步通信方式不要求双方同步，收发方可采用各自的时钟源，双方遵循异步的通信协议，以字符为数据传输单位，发送方传送字符的时间间隔不确定，发送效率比同步传送效率低。 <br />具体 <br /><br /><br />专业版:<br /><br />串行通信可以分为两种类型：同步通信、异步通信。<br /><br />　　1.异步通信的特点及信息帧格式： <br />　　以起止式异步协议为例，下图显示的是起止式一帧数据的格式： <br /><br />　　　　　　　<img height="176" src="http://www.eebyte.com/article/image/20030414_105-b-1.gif" width="488" /><br />　　　　　　　　　　　　　　　　　　　　　　图1 <br /><br />　　起止式异步通信的特点是：一个字符一个字符地传输，每个字符一位一位地传输，并且传输一个字符时，总是以“起始位”开始，以“停止位”结束,字符之间没有固定的时间间隔要求。每一个字符的前面都有一位起始位（低电平，逻辑值），字符本身由5-7位数据位组成，接着字符后面是一位校验位（也可以没有校验位），最后是一位或一位半或二位停止位，停止位后面是不定长的空闲位。停止位和空闲位都规定为高电平（逻辑值１），这样就保证起始位开始处一定有一个下跳沿。<br />　　从图中可看出，这种格式是靠起始位和停止位来实现字符的界定或同步的，故称为起止式协议。 <br />　　异步通信可以采用正逻辑或负逻辑，正负逻辑的表示如下表所示： <br /></p><table height="2" cellspacing="0" cellpadding="0" width="34%" align="center" border="1"><tbody><tr><td class="bottond" width="25%" height="9"> </td><td class="bottond" width="37%" height="9"><p align="center"><font color="#000000">逻辑0</font></p></td><td class="bottond" width="38%" height="9"><p align="center"><font color="#000000">逻辑1</font></p></td></tr><tr><td class="bottond" width="25%" height="1"><p align="center"><font color="#000000">正逻辑</font></p></td><td class="bottond" width="37%" height="1"><p align="center"><font color="#000000">低电平</font></p></td><td class="bottond" width="38%" height="1"><p align="center"><font color="#000000">高电平</font></p></td></tr><tr><td class="bottond" width="25%" height="1"><p align="center"><font color="#000000">负逻辑</font></p></td><td class="bottond" width="37%" height="1"><p align="center"><font color="#000000">高电平</font></p></td><td class="bottond" width="38%" height="1"><p align="center"><font color="#000000">低电平</font></p></td></tr></tbody></table><br />　　<span class="wenben">异步通信的信息格式如下边的表所示</span><br /><table height="1" cellspacing="0" cellpadding="0" width="35%" align="center" border="1"><center></center><tbody><tr><center><td class="bottond" width="25%" height="1"><p align="center"><font class="bottond" color="#666666">起始位</font></p></td></center><td class="bottond" width="27%" height="1"><p align="left"><font class="bottond" color="#666666">逻辑0</font></p></td><td class="bottond" width="48%" height="1"><p align="left"><font color="#666666">1位</font></p></td></tr><tr><center><td class="bottond" width="25%" height="1"><p align="center"><font color="#666666">数据位</font></p></td></center><td class="bottond" width="27%" height="1"><p align="left"><font color="#666666">逻辑0或1</font></p></td><td class="bottond" width="48%" height="1"><p align="left"><font color="#666666">5位、6位、7位、8位</font></p></td></tr><tr><center><td class="bottond" width="25%" height="1"><p align="center"><font color="#666666">校验位</font></p></td></center><td class="bottond" width="27%" height="1"><p align="left"><font color="#666666">逻辑0或1</font></p></td><td class="bottond" width="48%" height="1"><p align="left"><font color="#666666">1位或无</font></p></td></tr><tr><center><td class="bottond" width="25%" height="1"><p align="center"><font color="#666666">停止位</font></p></td></center><td class="bottond" width="27%" height="1"><p align="left"><font color="#666666">逻辑1</font></p></td><td class="bottond" width="48%" height="1"><p align="left"><font color="#666666">1位，1.5位或2位</font></p></td></tr><tr><center><td class="bottond" width="25%" height="1"><p align="center"><font color="#666666">空闲位</font></p></td></center><td class="bottond" width="27%" height="1"><p align="left"><font color="#666666">逻辑1</font></p></td><td class="bottond" width="48%" height="1"><p align="left"><font class="bottond" color="#666666">任意数量</font></p></td></tr></tbody></table><br /><br />　　<span class="wenben">注：表中位数的本质含义是信号出现的时间，故可有分数位，如1.5。</span><br />　　<span class="wenben">例：传送8位数据45H（0100,0101B），奇校验，1个停止位，则信号线上的波形象图2所示那样：异步通信的速率：若9600bps，每字符8位，1起始，1停止，无奇偶，则实际每字符传送10位，则960字符/秒。</span><p><br />　　　　　　　　　　　<img height="142" src="http://www.eebyte.com/article/image/20030414_105-b-2.gif" width="350" /></p><p><br />　　　　　　　　　　　　　　　　　　　　　　　　<span class="wenben">图2</span></p><p class="wenben">2.异步通信的接收过程</p><p class="wenben">　　接收端以“接收时钟”和“波特率因子”决定一位的时间长度。下面以波特率因子等于16（接收时钟每16个时钟周期，使接收移位寄存器移位一次）、正逻辑为例说明，如图3所示。<br />　　　　　　　　　　<img height="130" src="http://www.eebyte.com/article/image/20030414_105-b-3.gif" width="365" /></p><p></p><p class="wenben">　　　　　　　　　　　　　　　　　　　　　　图3</p><p class="wenben">　　（1）开始通信时，信号线为空闲（逻辑1）,当检测到由1到0的跳变时，开始对“接收时钟”计数。　</p><p class="wenben">　　（2）当计到8个时钟时，对输入信号进行检测，若仍为低电平，则确认这是“起始位”B，而不是干扰信号。</p><p class="wenben">　　（3）接收端检测到起始位后，隔16个接收时钟，对输入信号检测一次，把对应的值作为D0位数据。若为逻辑1, 作为数据位1；若为逻辑0，作为数据位0。</p><p class="wenben">　　（4）再隔16个接收时钟，对输入信号检测一次，把对应的值作为D1位数据。….，直到全部数据位都输入。</p><p class="wenben">　　（5）检测校验位P（如果有的话）。</p><p class="wenben">　　（6）接收到规定的数据位个数和校验位后,通信接口电路希望收到停止位S(逻辑1)，若此时未收到逻辑1，说明出现了错误，在状态寄存器中置“帧错误”标志。若没有错误，对全部数据位进行奇偶校验，无校验错时，把数据位从移位寄存器中送数据输入寄存器。若校验错，在状态寄存器中置奇偶错标志。</p><p class="wenben">　　（7）本幀信息全部接收完，把线路上出现的高电平作为空闲位。</p><p class="wenben">　　（8）当信号再次变为低时，开始进入下一幀的检测。</p><p class="wenben">　　3、异步通信的发送过程</p><p class="wenben">　　发送端以“发送时钟”和“波特率因子”决定一位的时间长度。</p><p class="wenben">　　（1）当初始化后，或者没有信息需要发送时，发送端输出逻辑1，即空闲位，空闲位可以有任意数量。</p><p class="wenben">　　（2）当需要发送时，发送端首先输出逻辑0，作为起始位。</p><p class="wenben">　　（3）接着，发送端首先发送D0位，直到各数据位发送完。</p><p class="wenben">　　（4）如果需要的话，发送端输出校验位。</p><p class="wenben">　　（5）最后，发送端输出停止位（逻辑1）。</p><p class="wenben">　　（6）如果没有信息需要发送时，发送端输出逻辑1，即空闲位，空闲位可以有任意数量。如果还有信息需要发送，转入第（2）步。</p><p class="wenben">　　对于以上发送、接收过程应注意以下几点：</p><p class="wenben">　　（1）接收端总是在每个字符的头部（即起始位）进行一次重新定位，因此发送端可以在字符之间插入不等长的空闲位，不影响接收端的接收。</p><p class="wenben">　　（2）发送端的发送时钟和接收端的接收时钟，其频率允许有一定差异，当频率差异在一定范围内，不会引起接收端检测错位，能够正确接收。并且这种频率差异不会因多个字符的连续接收而造成误差累计（因为每个字符的开始（起始位处）接收方均重新定位）。只有当发送时钟和接收时钟频率差异太大，引起接收端采样错位，才造成接收错误。</p><p><span class="wenben">　　（3）起始位、校验位、停止位、空闲位的信号，由“发送移位寄存器”自动插入。在接收方，“接收移位寄存器”接收到一帧完整信息（起始、数据、校验、停止）后，仅把数据的各位送至“数据输入寄存器”，即CPU从“数据输入寄存器”中读得的信息，只是有效数字，不包含起始位、校验位、停止位信息。</span><br /></p><p><br /><br />1、同步通信方式的特点：<br /><br />　　采用同步通信时，将许多字符组成一个信息组，这样，字符可以一个接一个地传输，但是，在每组信息（通常称为帧）的开始要加上同步字符，在没有信息要传输时，要填上空字符，因为同步传输不允许有间隙。在同步传输过程中，一个字符可以对应5～8位。当然，对同一个传输过程，所有字符对应同样的数位，比如说n位。这样，传输时，按每n位划分为一个时间片，发送端在一个时间片中发送一个字符，接收端则在一个时间片中接收一个字符。<br />同步传输时，一个信息帧中包含许多字符，每个信息帧用同步字符作为开始，一般将同步字符和空字符用同一个代码。在整个系统中，由一个统一的时钟控制发送端的发送和空字符用同一个代码。接收端当然是应该能识别同步字符的，当检测到有一串数位和同步字符相匹配时，就认为开始一个信息帧，于是，把此后的数位作为实际传输信息来处理。 <br />　　<b>2、面向字符的同步协议（IBM的BSC协议）</b><br />　　　　　　　<img height="155" src="http://www.eebyte.com/article/image/20030414_106-b-1.gif" width="371" /><br /><br />　　该协议规定了10个特殊字符（称为控制字符）作为信息传输的标志。其格式为<br />　　SYN SOH 标题 STX 数据块 ETB/ETX 块校验<br />　　SYN：同步字符（Synchronous character），每帧可加1个（单同步）或2个（双同步）同步字符。 <br />　　SOH：标题开始（Start of Header）。<br />　　标题：Header，包含源地址（发送方地址）、目的地址（接收方地址）、路由指示。<br />　　STX：正文开始（Start of Text）。<br />　　数据块：正文（Text），由多个字符组成。<br />　　ETB:块传输结束（end of transmission block）， 标识本数据块结束。<br />　　ETX：全文结束（end of text），（全文分为若干块传输）。<br />　　块校验：对从SOH开始，直到ETB/ETX字段的检验码。<br />　<b>　3、面向bit的同步协议（ISO的HDLC）</b><br />　　　　　　　　　　　　　　<img height="164" src="http://www.eebyte.com/article/image/20030414_106-b-2.gif" width="353" /><br /><br />　　一帧信息可以是任意位，用位组合标识帧的开始和结束。 帧格式为：<br />　　F场 A场 C场 I场 FC场 F场<br />　　F场：标志场;作为一帧的开始和结束，标志字符为8位，01111110。 <br />　　A场：地址场，规定接收方地址，可为8的整倍位。接收方检查每个地址字节的第1位，如果为"0"，则后边跟着另一<br />　　个地址字节。若为"1"，则该字节为最后一个地址字节。<br />　　C场：控制场。指示信息场的类型，8位或16位。若第1字节的第1位为0，则还有第2个字节也是控制场。<br />　　I场：信息场。要传送的数据。<br />　　FC场：帧校验场。16位循环冗余校验码CRC。除F场和自动插入的"0"位外，均参加CRC计算。<br />　　<b>4、同步通信的"0位插入和删除技术"</b><br />　　在同步通信中，一帧信息以一个（或几个）特殊字符开始，例如，F场=01111110B。<br />但在信息帧的其他位置，完全可能出现这些特殊字符，为了避免接收方把这些特殊字符误认为帧的开始，发送方采用“0位插入技术"，相应地，接收方采用"0位删除技术"。<br />　　发送方的0位插入：除了起始字符外，当连续出现5个1时，发送方自动插入一个0。使得在整个信息帧中，只有起始字符含有连续的6个1。<br />　　接收方的"0位删除技术"：接收方收到连续6个1，作为帧的起始，把连续出现5个1后的0自动删除。<br />　　<b>5、同步通信的"字节填充技术"</b><br />　　设需要传送的原始信息帧为：<br />　　SOT DATA EOT<br />　　节填充技术采用字符替换方式，使信息帧的DATA中不出现起始字符SOT和结束字符EOT。 <br />　　设按下表方式进行替换：<br />　　　　　　　DATA中的原字符 　　替换为<br />　　　　　　　SOT　　　　　　　　ESC X<br />　　　　　　　EOT 　　　　　　　 ESC Y<br />　　　　　　　ESC 　　　　　　　 ESC Z<br />　　 其中，ESC=1AH，X、Y、Z可指定为任意字符（除SOT、EOT、ESC外）。<br />　 　发送方按约定方式对需要发送的原始帧进行替换，并把替换后的新的帧发送给接收方。例如图所示：<br />　　　　　　　　　　　　　<img height="111" src="http://www.eebyte.com/article/image/20030414_106-b-3.gif" width="357" /><br /><br />　　接收方按约定方式进行相反替换，可以获得原始帧信息。<br />　　<b>6、异步通信和同步通信的比较</b><br />　　（1）异步通信简单，双方时钟可允许一定误差。同步通信较复杂，双方时钟的允许误差较小。<br />　　（2）异步通信只适用于点&lt;--&gt; 点，同步通信可用于点&lt;--&gt; 多。<br />　　（3）通信效率：异步通信低，同步通信高。 <br /><br /><br /><br /></p><img src ="http://www.blogjava.net/junky/aggbug/88659.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/junky/" target="_blank">junky</a> 2006-12-18 23:43 <a href="http://www.blogjava.net/junky/archive/2006/12/18/88659.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>快速精确的对数学表达式求值(转)</title><link>http://www.blogjava.net/junky/archive/2006/10/25/77240.html</link><dc:creator>junky</dc:creator><author>junky</author><pubDate>Wed, 25 Oct 2006 09:31:00 GMT</pubDate><guid>http://www.blogjava.net/junky/archive/2006/10/25/77240.html</guid><wfw:comment>http://www.blogjava.net/junky/comments/77240.html</wfw:comment><comments>http://www.blogjava.net/junky/archive/2006/10/25/77240.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/junky/comments/commentRss/77240.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/junky/services/trackbacks/77240.html</trackback:ping><description><![CDATA[步骤：
<ol><li>表达式语法分析 
</li><li>表达式检查 
</li><li>一步一步的求值 </li></ol><p><a name="N10119"><span class="smalltitle"><strong>表达式语法分析</strong></span></a></p><p>W3Eval 的数学表达式由数字、变量、操作符、函数和括号组成。除了缺省的十进制计数制外 W3Eval 还支持二进制、八进制和十六进制。这些以其它计数制计数的数必须以 <code><font face="Courier" size="2">#</font></code> 开头，并紧跟 <code><font face="Courier" size="2">b</font></code> 、 <code><font face="Courier" size="2">o</font></code> 或者 <code><font face="Courier" size="2">h</font></code> 来分别表示二进制、八进制或十六进制。 </p><p>W3Eval 的变量是不限长度的大写字母和数字序列，其首字符必须是字母。W3Eval 有一些预定义的变量，不过它也支持用户定义的变量。</p><p>W3Eval 支持带有固定或不定数量自变量的函数。 函数可分为以下几组：</p><ul><li>三角函数（sin、cos、tan、cot、sec、csc） 
</li><li>反三角函数（asin、acos、atan、atan2、acot、asec、acsc） 
</li><li>双曲线函数（sinh、cosh、tanh、coth、sech、csch） 
</li><li>反双曲线函数（asinh、acosh、atanh、acoth、asech、acsch） 
</li><li>指数函数（log、log2、log10、exp、exp2、exp10、sqrt、cur） 
</li><li>组合学函数（Combinatoric）（comb、combr、perm、permr、var、varr） 
</li><li>统计函数（sum、avg、min、max、stddev、count） 
</li><li>其它（abs、ceil、fact、floor、pow、random、rint、round、sign、frac、hypot、deg、rad、trunc、int） </li></ul><p>W3Eval 对表达式进行 <i>语法分析</i>，也就是指它识别出表达式的算术成分，并将它们转化成语言符号（token），然后把它们放入向量。表达式一旦处于这种状态，就为下面两步做好了准备：表达式检查和求值。 </p><p>W3Eval 的 <i>符号（token）</i>是算术表达式的组成部分； <i>记号（mark）</i>是独立的字符， 由 applet 使用，作为识别各种符号的内部标志。每种符号有唯一的 mark 与之对应。W3Eval 的表达式由表 1 所示的符号组成。 </p><p><a name=" "><span class="smalltitle"><strong>表 1. W3Eval 的符号</strong></span></a></p><p></p><table cellspacing="0" cellpadding="5" width="100%" border="1"><tbody><tr><td><strong>Token</strong></td><td><b>Mark</b></td><td><b>类</b></td></tr><tr><td>十进制数</td><td></td><td><code><font face="Courier" size="2">Double</font></code></td></tr><tr><td>二进制数</td><td></td><td><code><font face="Courier" size="2">String</font></code></td></tr><tr><td>十六进制数</td><td></td><td><code><font face="Courier" size="2">String</font></code></td></tr><tr><td>八进制数</td><td></td><td><code><font face="Courier" size="2">String</font></code></td></tr><tr><td>变量</td><td></td><td>Variable</td></tr><tr><td>函数</td><td></td><td><code><font face="Courier" size="2">Function</font></code></td></tr><tr><td>操作符</td><td></td><td><code><font face="Courier" size="2">Operator</font></code></td></tr><tr><td>开括号</td><td></td><td><code><font face="Courier" size="2">String</font></code></td></tr><tr><td>闭括号</td><td></td><td><code><font face="Courier" size="2">String</font></code></td></tr><tr><td>逗号</td><td></td><td><code><font face="Courier" size="2">String</font></code></td></tr></tbody></table><p>用以表示函数、操作符和变量类的定义如清单 1 所示：</p><br /><a name="code1"><b>清单 1. Function、Operator 和 Variable 类的定义</b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1"><tbody><tr><td><pre><code class="section"><font face="Lucida Console">public class Function
   {
   public String function;
   public int number_of_arguments;

   public Function( String function, int number_of_arguments )
      {
      this.function=function;
      this.number_of_arguments=number_of_arguments;
      }

   public String toString()
      {
      return function;
      }
   }

public class Operator
   {
   public String operator;
   public byte priority;

   public Operator( String operator, byte priority )
      {
      this.operator=operator;
      this.priority=priority;
      }

   public String toString()
      {
      return operator;
      }
   }

public class Variable
   {
   public String variable;
   public double value;

   public Variable( String variable, double value )
      {
      this.variable=variable;
      this.value=value;
      }

   public String toString()
      {
      return variable;
      }
   }
</font></code></pre></td></tr></tbody></table><br /><p><code><font face="Courier" size="2">Token</font></code> 类如清单 2 所示。 </p><br /><a name="listing2"><b>清单 2. Token 类</b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1"><tbody><tr><td><pre><code class="section"><font face="Lucida Console">public class Token
   {
   public Object token;
   public char mark;
   public int position;
   public int length;

   public Token ( Object token, char mark, int position, int length )
      {
      this.token=token;
      this.mark=mark;
      this.position=position;
      this.length=length;
      }

   public String toString()
      {
      return token.toString()+" ; "+mark+" ; "+position+" ; "+length+"
";
      }
   }
</font></code></pre></td></tr></tbody></table><br /><p><a name="N10237"><span class="smalltitle"><strong>表达式检查</strong></span></a></p><p>检查正规表达式正确性的所有代码都在一个独立的类中。详细的表达式检查能够确定错误确切的类型和位置。 错误检查有七类：</p><p><b>括号检查。</b>W3Eval 的表达式可以包含三种括号：标准圆括号、方括号和花括号。如果表达式包含相同数量的开括号和闭括号，并且每个开括号与一个相应的同种闭括号相匹配，则表达式的括号语法正确。三种括号在语义上等价，如下面的代码段所示。 </p><br /><a name="listing3"><b>清单 3. 三种括号</b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1"><tbody><tr><td><pre><code class="section"><font face="Lucida Console">import java.util.Stack;

public class Parentheses_check
   {

   public static boolean is_open_parenthesis( char c )
      {
      if ( c=='(' || c=='[' || c=='{' )
         return true;
      else
         return false;
      }

   public static boolean is_closed_parenthesis( char c )
      {
      if ( c==')' || c==']' || c=='}' )
         return true;
      else
         return false;
      }

   private static boolean parentheses_match( char open, char closed )
      {
      if ( open=='(' &amp;&amp; closed==')' )
         return true;
      else if ( open=='[' &amp;&amp; closed==']' )
         return true;
      else if ( open=='{' &amp;&amp; closed=='}' )
         return true;
      else
         return false;
      }

   public static boolean parentheses_valid( String exp )
      {
      Stack       s = new Stack();
      int         i;
      char        current_char;
      Character   c;
      char        c1;
      boolean     ret=true;

      for ( i=0; i &lt; exp.length(); i++ )
         {

         current_char=exp.charAt( i );

         if ( is_open_parenthesis( current_char ) )
            {
            c=new Character( current_char );
            s.push( c );
            }
         else if ( is_closed_parenthesis( current_char ) )
            {
            if ( s.isEmpty() )
               {
               ret=false;
               break;
               }
            else
               {
               c=(Character)s.pop();
               c1=c.charValue();
               if ( !parentheses_match( c1, current_char ) )
                  {
                  ret=false;
                  break;
                  }
               }
            }
         }

      if ( !s.isEmpty() )
         ret=false;

      return ret;
      }
   }
</font></code></pre></td></tr></tbody></table><br /><p><b>token 检查。</b>检查表达式语法。确保表达式所有部分都被认为是合法的。 </p><p><b>表达式开头的检查</b>（请参阅 <a href="http://www-128.ibm.com/developerworks/cn/java/j-w3eva/index.html#listing4"><font color="#996699">清单 4</font></a>） <b>。</b>确保表达式从合法的符号开始。不可以用操作符、逗号或闭括号作为表达式的开始符。 </p><br /><a name="listing4"><b>清单 4. 正确的表达式开头的检查</b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1"><tbody><tr><td><pre><code class="section"><font face="Lucida Console">private static boolean begin_check( Vector tokens, Range r, StringBuffer err )
   {
   char     mark;
   Token    t;

   t=(Token)tokens.elementAt( 0 );
   mark=t.mark;

   if ( mark=='P' )
      err.append( Messages.begin_operator );
   else if ( mark==')' )
      err.append( Messages.begin_parenthesis );
   else if ( mark=='Z' )
      err.append ( Messages.begin_comma );
   else
      return true;

   r.start=0;
   r.end=t.length;
   return false;
   }
</font></code></pre></td></tr></tbody></table><br /><p><b>表达式末尾的检查。</b>确保表达式以合法符号结束。不可以用操作符、函数、逗号或开括号作为表达式结束符。 </p><p><b>符号序列的检查。</b>检查表达式中的符号序列。在下面的表格中，若 X 轴上的符号和 Y 轴上的符号对应的交界处用 X 作了记号，则相应 X 轴上的符号可以接在 Y 轴上符号的后面。 </p><p><a name=" "><span class="smalltitle"><strong>表 2. 合法的符号序列</strong></span></a></p><p></p><table cellspacing="0" cellpadding="5" width="50%" border="1"><tbody><tr><td><strong></strong></td></tr><tr><td width="20"><strong>_</strong></td><td width="20" bgcolor="#cccccc"><b>D</b></td><td width="20" bgcolor="#cccccc"><b>B</b></td><td width="20" bgcolor="#cccccc"><b>H</b></td><td width="20" bgcolor="#cccccc"><b>O</b></td><td width="20" bgcolor="#cccccc"><b>V</b></td><td width="20" bgcolor="#cccccc"><b>F</b></td><td width="20" bgcolor="#cccccc"><b>P</b></td><td width="20" bgcolor="#cccccc"><b>(</b></td><td width="20" bgcolor="#cccccc"><b>)</b></td><td width="20" bgcolor="#cccccc"><b>Z</b></td></tr><tr><td bgcolor="#cccccc"><b>D</b></td><td>_</td><td>_</td><td>_</td><td>_</td><td>_</td><td>_</td><td>犠</td><td>_</td><td>犠</td><td>犠</td></tr><tr><td bgcolor="#cccccc"><b>B</b></td><td>_</td><td>_</td><td>_</td><td>_</td><td>_</td><td>_</td><td>犠</td><td>_</td><td>犠</td><td>犠</td></tr><tr><td bgcolor="#cccccc"><b>H</b></td><td>_</td><td>_</td><td>_</td><td>_</td><td>_</td><td>_</td><td>犠</td><td>_</td><td>犠</td><td>犠</td></tr><tr><td bgcolor="#cccccc"><b>O</b></td><td>_</td><td>_</td><td>_</td><td>_</td><td>_</td><td>_</td><td>犠</td><td>_</td><td>犠</td><td>犠</td></tr><tr><td bgcolor="#cccccc"><b>V</b></td><td>_</td><td>_</td><td>_</td><td>_</td><td>_</td><td>_</td><td>犠</td><td>_</td><td>犠</td><td>犠</td></tr><tr><td bgcolor="#cccccc"><b>F</b></td><td>_</td><td>_</td><td>_</td><td>_</td><td>_</td><td>_</td><td>_</td><td>犠</td><td>_</td><td>_</td></tr><tr><td bgcolor="#cccccc"><b>P</b></td><td>犠</td><td>犠</td><td>犠</td><td>犠</td><td>犠</td><td>犠</td><td>_</td><td>犠</td><td>_</td><td>_</td></tr><tr><td bgcolor="#cccccc"><b>(</b></td><td>犠</td><td>犠</td><td>犠</td><td>犠</td><td>犠</td><td>犠</td><td>_</td><td>犠</td><td>_</td><td>_</td></tr><tr><td bgcolor="#cccccc"><b>)</b></td><td>_</td><td>_</td><td>_</td><td>_</td><td>_</td><td>_</td><td>犠</td><td>_</td><td>犠</td><td>犠</td></tr><tr><td bgcolor="#cccccc"><b>Z</b></td><td>犠</td><td>犠</td><td>犠</td><td>犠</td><td>犠</td><td>犠</td><td>_</td><td>犠</td><td>_</td><td>_</td></tr></tbody></table><p><b>函数检查。</b>确保表达式中所有函数的自变量数量正确。 </p><p><b>逗号检查。</b>逗号只能用于分隔函数的自变量。若用于表达式其它地方，就不合法。 </p><p><a name="N10484"><span class="smalltitle"><strong>一步一步的求值</strong></span></a></p><p>只有能顺利通过以上概括的所有检查的表达式，W3Eval 才求值。从而确保内建于 W3Eval 中的前提条件不会出现问题。后面的算法用于单步执行表达式求值：</p><ol><li>找出嵌入最深的那对括号。 
</li><li>在这对括号中，找出优先级最高的操作符。 
</li><li>若这对括号中没有操作符： 
<ul><li>如果表达式再不包含任何其它的括号，求值（过程）完成。 
</li><li>如果表达式包含括号，但不包含操作符，则存在一个函数。对函数求值，然后转到步骤 5。 </li></ul></li><li>获取操作数并执行运算。 
</li><li>从向量中除去用过的符号并在同一位置放入结果。 
</li><li>除去冗余括号。 
</li><li>将向量中剩余的符号结合到字符串并在屏幕上显示结果。 </li></ol><p>现在，我们将更为详细的查看算法的每一步，同时查看大部分有意思的代码片段。</p><p><b>步骤 1：</b>为避免括号的处理，W3Eval 确定哪个子表达式处于嵌套最深的那对括号中。这项任务需要两步。第一步，W3Eval 必须找出第一个闭括号： </p><br /><a name="listing5"><b>清单 5. 找出第一个闭括号</b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1"><tbody><tr><td><pre><code class="section"><font face="Lucida Console">public static int pos_first_closed_parenthesis( Vector tokens )
   {
   Token   t;

   for ( int i=0; i&lt;tokens.size(); i++ )
      {
      t=(Token)tokens.elementAt( i );
      if ( t.mark==')' )
         return i;
      }
   return 0;
   }
</font></code></pre></td></tr></tbody></table><br /><p>第二步，找出与第一步找到的闭括号相匹配的开括号，如 <a href="http://www-128.ibm.com/developerworks/cn/java/j-w3eva/index.html#listing6"><font color="#996699">清单 6 所示</font></a>。 </p><br /><a name="listing6"><b>清单 6. 找出匹配的开括号</b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1"><tbody><tr><td><pre><code class="section"><font face="Lucida Console">public static int pos_open_parenthesis( Vector tokens, int closed_parenthesis )
   {
   int      i;
   Token    t;

   i=closed_parenthesis-2;

   while ( i&gt;=0 )
      {
      t=(Token)tokens.elementAt( i );
      if ( t.mark=='(' )
         {
         return i;
         }
      i--;
      }
   return 0;
   }
</font></code></pre></td></tr></tbody></table><br /><p><b>步骤 2：</b>要实现求值的单步执行，W3Eval 在嵌套最深的那对括号中找出优先级最高的操作符。（操作符的优先级已硬编码到 applet 中；请参阅 <a href="http://www-128.ibm.com/developerworks/cn/java/j-w3eva/index.html#resources"><font color="#996699">参考资料</font></a>以获取完整的代码清单。） </p><br /><a name="listing7"><b>清单 7. 找出优先级最高的操作符</b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1"><tbody><tr><td><pre><code class="section"><font face="Lucida Console">public static int pos_operator( Vector tokens, Range r )
   {
   byte     max_priority=Byte.MAX_VALUE;
   int      max_pos=0;

   byte     priority;
   String   operator;
   Token    t;

   for ( int i=r.start+2; i&lt;=r.end-2; i++ )
      {
      t=(Token)tokens.elementAt( i );
      if ( t.mark!='P' )
         continue;
      priority=((Operator)t.token).priority;
      operator=((Operator)t.token).operator;

      if ( priority &lt; max_priority || ( operator.equals("^") ||
         operator.equals("**") ) &amp;&amp; priority == max_priority )
         {
         max_priority=priority;
         max_pos=i;
         }
      }
   return max_pos;
   }
</font></code></pre></td></tr></tbody></table><br /><p><b>步骤 3：</b>如果表达式中不包含其它括号，求值的过程就完成。如果表达式包含括号，但不包含操作符，则存在需要求值的函数。 </p><br /><a name="listing8"><b>清单 8. 检查是否还有其它操作符</b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1"><tbody><tr><td><pre><code class="section"><font face="Lucida Console">...
int poz_max_op=pos_operator( tokens, range );
// if there are no operators
if ( poz_max_op==0 )
   {
   if ( no_more_parentheses )
      {
      return false;
      }
   else
      {
      double   result;
      result=function_result( tokens, range.start-1 );
      function_tokens_removal( tokens, range.start-1 );

      t = new Token ( new Double(result), 'D', 0, 0 );
      tokens.setElementAt( t, range.start-1 );

      parentheses_removal( tokens, range.start-1 );
      return true;
      }
   }
...
</font></code></pre></td></tr></tbody></table><br /><p><b>步骤 4：</b>所有的操作符都是二元的，也就是说第一个操作数位于操作符之前，第二个操作符位于操作符之后。 </p><br /><a name="listing9"><b>清单 9. 获取操作数并执行运算</b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1"><tbody><tr><td><pre><code class="section"><font face="Lucida Console">...
double operand1, operand2;

// first operand is before...
t=(Token)tokens.elementAt( poz_max_op-1 );
operand1=operand_value( t );

// ...and second operand is after operator
t=(Token)tokens.elementAt( poz_max_op+1 );
operand2=operand_value( t );

// operator
t=(Token)tokens.elementAt( poz_max_op );
String op=((Operator)t.token).operator;

double result=operation_result( operand1, operand2, op );

tokens.removeElementAt( poz_max_op+1 );
tokens.removeElementAt( poz_max_op );

t = new Token ( new Double(result), 'D', 0, 0 );
tokens.setElementAt( t, poz_max_op-1 );

parentheses_removal( tokens, poz_max_op-1 );
...
</font></code></pre></td></tr></tbody></table><br /><p>操作数可以是变量，还可以是十进制、十六进制、八进制或二进制数。</p><br /><a name="listing10"><b>清单 10. 获取操作数</b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1"><tbody><tr><td><pre><code class="section"><font face="Lucida Console">public static double operand_value( Token t )
   {
   if ( t.mark=='V' )
      return ((Variable)t.token).value;
   else if ( t.mark=='D' )
      return ((Double)t.token).doubleValue();
   else if ( t.mark=='H' )
      return base_convert( ((String)t.token).substring(2), 16 );
   else if ( t.mark=='O' )
      return base_convert( ((String)t.token).substring(2), 8 );
   else if ( t.mark=='B' )
      return base_convert( ((String)t.token).substring(2), 2 );
   }
</font></code></pre></td></tr></tbody></table><br /><p>接下来的方法将不同计数制的数转化为十进制的形式。</p><br /><a name="listing11"><b>清单 11. 将数转化为十进制数</b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1"><tbody><tr><td><pre><code class="section"><font face="Lucida Console">public static long base_convert( String s, int base )
   {
   long r=0;
   int i, j;

   for ( i=s.length()-1, j=0; i&gt;=0; i--, j++ )
      r=r+digit_weight( s.charAt( i ) )*(long)Math.pow( base, j );
   return r;
   }

public static int digit_weight( char c )
   {
   if ( Character.isDigit( c ) )
      return c-48;
   else if ( 'A'&lt;=c &amp;&amp; c&lt;='f' )
      return c-55;
   else if ( 'a'&lt;=c &amp;&amp; c&lt;='f' )
      return c-87;
   return -1;
   }
</font></code></pre></td></tr></tbody></table><br /><p>一旦确定操作数和操作符后，就可以执行运算了，如 <a href="http://www-128.ibm.com/developerworks/cn/java/j-w3eva/listing12.html"><font color="#5c81a7">清单 12</font></a>所示。 </p><p><b>步骤 5：</b>在这步中，W3Eval 从向量中除去用过的符号并在同一位置放入结果。对于函数求值这类情况，除去的是函数、括号、自变量和逗号；而对于操作符求值这类情况而言，除去的则是操作数和操作符。 </p><p><b>步骤 6：</b>在求值的这一步，W3Eval 从表达式中除去冗余括号。 </p><br /><a name="listing13"><b>清单 13. 除去冗余括号</b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1"><tbody><tr><td><pre><code class="section"><font face="Lucida Console">private static void parentheses_removal( Vector tokens, int pos )
   {
   if ( 
      pos&gt;1 &amp;&amp;
amp;&amp;&amp;
amp;
      ((Token)tokens.elementAt( poz-2 )).mark!='F' &amp;&amp;
amp;&amp;&amp;
amp;
      ((Token)tokens.elementAt( poz-1 )).mark=='(' &amp;&amp;
amp;&amp;&amp;
amp;
      ((Token)tokens.elementAt( poz+1 )).mark==')'
      ||
      pos==1 &amp;&amp;
amp;&amp;&amp;
amp;
      ((Token)tokens.elementAt( 0 )).mark=='(' &amp;&amp;
amp;&amp;&amp;
amp;
      ((Token)tokens.elementAt( 2 )).mark==')'
      )
      {
      tokens.removeElementAt( poz+1 );
      tokens.removeElementAt( poz-1 );
      }
   return;
   }
</font></code></pre></td></tr></tbody></table><br /><p><b>步骤 7：</b>在求值的最后一步，向量中剩余的符号被结合到字符串，并在屏幕上显示。 </p><br /><a name="listing14"><b>清单 14. 结合符号并显示结果</b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1"><tbody><tr><td><pre><code class="section"><font face="Lucida Console">public static String token_join( Vector tokens )
   {
   String   result=new String();
   Token    t;

   for ( int i=0; i &lt; tokens.size(); i++ )
      {
      t=(Token)tokens.elementAt( i );

      if ( t.mark=='D' )
         {
         double n=((Double)t.token).doubleValue();
         result=result + formated_number( n );
         }
      else
         result=result + t.token;

      if ( result.endsWith( ".0" ) )
         result=result.substring( 0, result.length()-2 );
      result=result + " ";
      }
   return result;
   }
</font></code></pre></td></tr></tbody></table><br /><a name="9"><br /><table cellspacing="0" cellpadding="0" width="100%" border="0"><tbody><tr><td><font face="Lucida Console"><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br /><img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></font></td></tr></tbody></table><table class="no-print" cellspacing="0" cellpadding="0" align="right"><tbody><tr align="right"><td><font face="Lucida Console"><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br /></font><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td valign="center"><font face="Lucida Console"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br /></font></td><td valign="top" align="right"><a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-w3eva/index.html#main"><b><font face="Verdana" color="#996699">回页首</font></b></a></td></tr></tbody></table></td></tr></tbody></table><br /><br /><p><a name="h35212"><span class="atitle"><strong><font size="4">结论</font></strong></span></a></p><p>本文分析了一个 applet ，它能一步一步的对算术表达式求值。同时还按顺序回顾了最有意思的代码片段，并论述了两种不同的表达式求值方法。</p><p>下一版 W3Eval 有望在各方面得到增强，包括有能力添加用户定义的功能；支持分数、复数和矩阵；改良的图形用户界面（GUI）；大小和速度优化以及安全性方面的增强。我鼓励您提供您自己对于增强方面的设想。</p><p>我希望您会发现 W3Eval 是个对表达式求值有益的在线工具，它在某种程度上比经典的方法更简单自然。我还期待这里谈到的代码和算法使您明白 Java 语言有助于处理数学问题。</p><br /><table cellspacing="0" cellpadding="0" width="100%" border="0"><tbody><tr><td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br /><img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td></tr></tbody></table><table class="no-print" cellspacing="0" cellpadding="0" align="right"><tbody><tr align="right"><td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br /><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td valign="center"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br /></td><td valign="top" align="right"><a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-w3eva/index.html#main"><b><font face="Verdana" color="#996699">回页首</font></b></a></td></tr></tbody></table></td></tr></tbody></table><br /><br /><p><a name="resources"><span class="atitle"><strong><font size="4">参考资料 </font></strong></span></a></p><ul><li>您可以参阅本文在 developerWorks 全球站点上的 <a href="http://www.ibm.com/developerworks/library/j-w3eval/index.html"><font color="#5c81a7">英文原文</font></a>. <br /><br /></li><li><a href="http://geodet.geof.hr/~mstepan/nik/W3Eval.html"><font color="#5c81a7">W3Eval applet</font></a>是免费的，它的 <a href="http://geodet.geof.hr/~mstepan/nik/help.html"><font color="#5c81a7">帮助</font></a>有助于您解决问题。 <br /><br /><br /></li><li>这张表格展示了 <a href="http://geodet.geof.hr/~mstepan/nik/operators.html"><font color="#5c81a7">W3Eval 操作符的优先级</font></a>。 <br /><br /><br /></li><li>请阅读波兰数学家 <a href="http://www-groups.dcs.st-and.ac.uk/~history/Mathematicians/Lukasiewicz.html"><font color="#5c81a7">Jan Lukasiewicz</font></a>的传记。 <br /><br /><br /></li><li>Donald Knuth，计算机科学领域卓越的学者，曾详尽的就算法的设计和分析撰写和演讲。他的 <a href="http://www-cs-faculty.stanford.edu/~knuth/"><font color="#5c81a7">主页</font></a>提供最近出版的有关其作品的论文和信息的链接。 <br /><br /><br /></li><li>有兴趣随意编写 applet 吗？可以查看我们的教程 <a href="http://www.ibm.com/developerworks/education.nsf/java-onlinecourse-bytitle/95CA3B951560F6FD852567570076D326?OpenDocument"><font color="#5c81a7">Building a Java applet</font></a>（developerWorks，1999 年）以获得一步一步的指导。 <br /><br /><br /></li><li>您会觉得 <a href="http://www.ibiblio.org/javafaq/javafaq.html"><font color="#5c81a7">Java FAQ</font></a>很有用。 <br /><br /><br /></li><li>还有很多有关 applet 的信息在 Peter Van Der Linden（Prentice Hall PTR/Sun Microsystems 出版社出版，1998 年 12 月）的 <i>Just Java 2</i>中。 <br /><br /><br /></li><li>由 Ken Arnold、James Gosling 和 David Holmes 撰写的 <a href="http://www.amazon.com/exec/obidos/ASIN/0201704331/qid=997216269/sr=2-2/102-7082828-4831324"><font color="#5c81a7"><i>The Java Programming Language</i></font></a>（Addison Wesley 出版社出版，2000 年 12 月）包含有益的关于集合的信息。 <br /><br /><br /></li><li>学习 Martin Bastiaan 的 <a href="http://www.ibm.com/developerworks/java/library/walk-in-the-park.html"><font color="#5c81a7">“A Walk in the Park”</font></a>（developerWorks，1998 年 1 月），了解更多有关 applet 的知识。 <br /><br /><br /></li><li><a href="http://www.ibm.com/software/ad/vajava/"><font color="#5c81a7">VisualAge for Java</font></a>使 applet 的开发变得轻而易举。 <br /><br /><br /></li><li>在 <a href="http://www-128.ibm.com/developerworks/cn/java/index.html"><font color="#5c81a7">developerWorks Java 技术专区</font></a>查找更多 Java 参考资料。 <br /></li></ul><br /><table cellspacing="0" cellpadding="0" width="100%" border="0"><tbody><tr><td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br /><img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td></tr></tbody></table><table class="no-print" cellspacing="0" cellpadding="0" align="right"><tbody><tr align="right"><td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br /><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td valign="center"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br /></td><td valign="top" align="right"><a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-w3eva/index.html#main"><b><font face="Verdana" color="#996699">回页首</font></b></a></td></tr></tbody></table></td></tr></tbody></table><br /><br /><p><a name="author"><span class="atitle"><strong><font size="4">关于作者</font></strong></span></a></p><table cellspacing="0" cellpadding="0" width="100%" border="0"><tbody><tr><td colspan="3"><strong><font size="4"><img height="5" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /></font></strong></td></tr><tr valign="top" align="left"><td><p><strong><font size="4"><img height="80" alt="Author photo" src="http://www-128.ibm.com/developerworks/cn/i/p-stepan.jpg" width="64" align="left" /></font></strong></p></td><td><strong><font size="4"><img height="5" alt="" src="http://www.ibm.com/i/c.gif" width="4" /></font></strong></td><td width="100%"><p>Nikola Stepan 是 ABIT Ltd. 的软件工程师，他在那里从事银行业软件的设计和开发。他有广博的信息系统方面的学术背景和丰富的编程经验（从低级编程到信息系统）。他特别喜欢面向对象编程语言、关系数据库、因特网编程和系统编程。他于 1999 年在克罗地亚 Varazdin 的 Faculty of Organisation and Informatic 获得信息系统学士学位。他会说克罗地亚语、英语和一点德语。请通过 <a href="mailto:nikola.stepan@vz.tel.hr"><font color="#5c81a7">nikola.stepan@vz.tel.hr</font></a>与 Nikola 联系。 </p></td></tr></tbody></table><br /></a><img src ="http://www.blogjava.net/junky/aggbug/77240.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/junky/" target="_blank">junky</a> 2006-10-25 17:31 <a href="http://www.blogjava.net/junky/archive/2006/10/25/77240.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>