﻿<?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>C++博客-KISS(Keep It Simple, Standard)-随笔分类-Arithmetic(算法)</title><link>http://www.cppblog.com/QUIRE-0216/category/6049.html</link><description /><language>zh-cn</language><lastBuildDate>Thu, 22 May 2008 13:35:27 GMT</lastBuildDate><pubDate>Thu, 22 May 2008 13:35:27 GMT</pubDate><ttl>60</ttl><item><title>关于Dijkstra算法我的理解（下）</title><link>http://www.cppblog.com/QUIRE-0216/archive/2008/02/01/42356.html</link><dc:creator>QUIRE-0216</dc:creator><author>QUIRE-0216</author><pubDate>Fri, 01 Feb 2008 09:09:00 GMT</pubDate><guid>http://www.cppblog.com/QUIRE-0216/archive/2008/02/01/42356.html</guid><wfw:comment>http://www.cppblog.com/QUIRE-0216/comments/42356.html</wfw:comment><comments>http://www.cppblog.com/QUIRE-0216/archive/2008/02/01/42356.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/QUIRE-0216/comments/commentRss/42356.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/QUIRE-0216/services/trackbacks/42356.html</trackback:ping><description><![CDATA[<img style="BORDER-LEFT-COLOR: #ffcc99; BORDER-BOTTOM-COLOR: #ffcc99; BORDER-TOP-COLOR: #ffcc99; BORDER-RIGHT-COLOR: #ffcc99" height=197 alt="" src="http://www.cppblog.com/images/cppblog_com/quire-0216/2.jpg" width=591 border=2><br>这步还有句要说的就是：（<u style="COLOR: red"><span style="COLOR: red">在把ＯＰＥＮ表中最优值的节点插入　ＣＬＯＳＥ表中时如果在ＣＬＯＳＥ表中已经存在那就要比较，如果存在的节点的权值比要插入的大，就要把存在的替换掉（节点中所有内容</span><span style="COLOR: red">），否则就忽略</span></u>）．<br><br>第３步：就是重复第２步骤（示例图如下）<br><img style="BORDER-LEFT-COLOR: #ffcc99; BORDER-BOTTOM-COLOR: #ffcc99; BORDER-TOP-COLOR: #ffcc99; BORDER-RIGHT-COLOR: #ffcc99" height=160 alt="" src="http://www.cppblog.com/images/cppblog_com/quire-0216/3.jpg" width=585 border=2><br>我想因该明白了吧！<br><br><img style="BORDER-LEFT-COLOR: #ffcc99; BORDER-BOTTOM-COLOR: #ffcc99; BORDER-TOP-COLOR: #ffcc99; BORDER-RIGHT-COLOR: #ffcc99" height=167 alt="" src="http://www.cppblog.com/images/cppblog_com/quire-0216/4.jpg" width=582 border=2><br><br><img style="BORDER-LEFT-COLOR: #ffcc99; BORDER-BOTTOM-COLOR: #ffcc99; BORDER-TOP-COLOR: #ffcc99; BORDER-RIGHT-COLOR: #ffcc99" height=181 alt="" src="http://www.cppblog.com/images/cppblog_com/quire-0216/5.jpg" width=580 border=2><br><br><img style="BORDER-LEFT-COLOR: #ffcc99; BORDER-BOTTOM-COLOR: #ffcc99; BORDER-TOP-COLOR: #ffcc99; BORDER-RIGHT-COLOR: #ffcc99" height=191 alt="" src="http://www.cppblog.com/images/cppblog_com/quire-0216/6.jpg" width=580 border=2><br><br><img style="BORDER-LEFT-COLOR: #ffcc99; BORDER-BOTTOM-COLOR: #ffcc99; BORDER-TOP-COLOR: #ffcc99; BORDER-RIGHT-COLOR: #ffcc99" height=210 alt="" src="http://www.cppblog.com/images/cppblog_com/quire-0216/7.jpg" width=580 border=2><br><br><img style="BORDER-LEFT-COLOR: #ffcc99; BORDER-BOTTOM-COLOR: #ffcc99; BORDER-TOP-COLOR: #ffcc99; BORDER-RIGHT-COLOR: #ffcc99" height=240 alt="" src="http://www.cppblog.com/images/cppblog_com/quire-0216/8.jpg" width=575 border=2><br>好了最后一张完工！<br><img style="BORDER-LEFT-COLOR: #ffcc99; BORDER-BOTTOM-COLOR: #ffcc99; BORDER-TOP-COLOR: #ffcc99; BORDER-RIGHT-COLOR: #ffcc99" height=231 alt="" src="http://www.cppblog.com/images/cppblog_com/quire-0216/9.jpg" width=578 border=2><br>终点（12节点）找到了是吧！我想因该明白了吧！<br>
<img src ="http://www.cppblog.com/QUIRE-0216/aggbug/42356.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/QUIRE-0216/" target="_blank">QUIRE-0216</a> 2008-02-01 17:09 <a href="http://www.cppblog.com/QUIRE-0216/archive/2008/02/01/42356.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于Dijkstra算法我的理解（上）</title><link>http://www.cppblog.com/QUIRE-0216/archive/2008/02/01/42351.html</link><dc:creator>QUIRE-0216</dc:creator><author>QUIRE-0216</author><pubDate>Fri, 01 Feb 2008 08:13:00 GMT</pubDate><guid>http://www.cppblog.com/QUIRE-0216/archive/2008/02/01/42351.html</guid><wfw:comment>http://www.cppblog.com/QUIRE-0216/comments/42351.html</wfw:comment><comments>http://www.cppblog.com/QUIRE-0216/archive/2008/02/01/42351.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/QUIRE-0216/comments/commentRss/42351.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/QUIRE-0216/services/trackbacks/42351.html</trackback:ping><description><![CDATA[<p>最近做了路径搜索,看了网上的描述真是晦涩,所以自己就整理下!<br>图画的不太好, :)<br>绿色的是节点,红色的为权值,箭头为可通行的标志.<br><img style="BORDER-LEFT-COLOR: #ffcc99; BORDER-BOTTOM-COLOR: #ffcc99; BORDER-TOP-COLOR: #ffcc99; BORDER-RIGHT-COLOR: #ffcc99" height=449 alt="" src="http://www.cppblog.com/images/cppblog_com/quire-0216/shilitu.jpg" width=576 border=2><br>现在我们要从 0 节点 到 12 节点 找一条最优路径:<br>首先咱们要解决NODE点存贮的信息(结构):<br>struct NodeBaseInfo<br>{<br>&nbsp;&nbsp;&nbsp;unsigned short nNodeID;　　　//番号<br>&nbsp;&nbsp;&nbsp;unsigned long&nbsp; nMeasure;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//权值<br>&nbsp;&nbsp; NodeBaseInfo *pParent;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//父节点<br>};<br><br>我写了简单的结构大家可以根据自己需要定义（定义这个结构是为了更好理解）<br>下面讲的是最主要的了：<br>DIJKSTAR算法中要定义两个表：OPEN 和 CLOSE&nbsp; （其实可以看作链表）<br>他的原理就是把没有遍历的点放在 OPEN 表中，把从 OPEN表中遍历到的最短权值的点放入<br>CLOSE 表中，当插入 CLOSE表中的节点的番号于我们要的重点时算法结束；然后按照父节点（pParent）<br>向上递归就可以得到我们要的最优路径了。<br><br>第一步：应为 OPEN 和CLOSE表都是空的，把起点（0节点）插入CLOSE标中，它的权值为0。把起点（0节点）附近的节点（因该为可通行的）插入OPEN 表中（<u style="COLOR: red">最好按权值从大道小的顺序插入，这样取得最优值时，这样速度就会很快</u>）。（如示例图）<br><img style="BORDER-LEFT-COLOR: #ffcc99; BORDER-BOTTOM-COLOR: #ffcc99; BORDER-TOP-COLOR: #ffcc99; BORDER-RIGHT-COLOR: #ffcc99" height=438 alt="" src="http://www.cppblog.com/images/cppblog_com/quire-0216/1.jpg" width=505 border=2><br>第2步：从OPEN表中找到权值最小的节点，把它插入CLOSE 表中, 把这个节点的可连通的节点查入ＯＰＥＮ<br>表，（<span style="COLOR: red"><u>如果ＯＰＥＮ表中存在要查入的点，如果要插入的节点的权值比已经存在的小，就把已经查入的权值该为最小的，如果要插入的节点的权值比已经存在的大，就忽落它</u></span>．）<br>（为了更好的理解我把父节点也加入了，如示例图）<br><br></p>
<img src ="http://www.cppblog.com/QUIRE-0216/aggbug/42351.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/QUIRE-0216/" target="_blank">QUIRE-0216</a> 2008-02-01 16:13 <a href="http://www.cppblog.com/QUIRE-0216/archive/2008/02/01/42351.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用移位、加减法实现整数开平方算法的方法(转)</title><link>http://www.cppblog.com/QUIRE-0216/archive/2008/01/23/41714.html</link><dc:creator>QUIRE-0216</dc:creator><author>QUIRE-0216</author><pubDate>Wed, 23 Jan 2008 06:21:00 GMT</pubDate><guid>http://www.cppblog.com/QUIRE-0216/archive/2008/01/23/41714.html</guid><wfw:comment>http://www.cppblog.com/QUIRE-0216/comments/41714.html</wfw:comment><comments>http://www.cppblog.com/QUIRE-0216/archive/2008/01/23/41714.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/QUIRE-0216/comments/commentRss/41714.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/QUIRE-0216/services/trackbacks/41714.html</trackback:ping><description><![CDATA[<p>本算法只采用移位、加减法、判断和循环实现，因为它不需要浮点运算，也不需要乘除运算，因此可以很方便地运用到各种芯片上去。</p>
<p>我们先来看看10进制下是如何手工计算开方的。<br>先看下面两个算式，<br>x = 10*p + q&nbsp; (1)<br>公式(1)左右平方之后得：<br>x^2 = 100*p^2 + 20pq + q^2 (2)<br>现在假设我们知道x^2和p，希望求出q来，求出了q也就求出了x^2的开方x了。<br>我们把公式(2)改写为如下格式：<br>q = (x^2 - 100*p^2)/(20*p+q) (3)</p>
<p>这个算式左右都有q，因此无法直接计算出q来，因此手工的开方算法和手工除法算法一样有一步需要猜值。</p>
<p>我们来一个手工计算的例子：计算1234567890的开方</p>
<p>首先我们把这个数两位两位一组分开，计算出最高位为3。也就是(3)中的p，最下面一行的334为余数，也就是公式(3)中的(x^2 - 100*p^2)近似值<br>&nbsp;&nbsp;&nbsp; 3<br>&nbsp; ---------------<br>&nbsp;/ 12 34 56 78 90<br>&nbsp;&nbsp;&nbsp; 9<br>&nbsp; ---------------<br>&nbsp;/&nbsp; 3 34</p>
<p>下面我们要找到一个0-9的数q使它最接近满足公式(3)。我们先把p乘以20写在334左边：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp; q<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;---------------<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; / 12 34 56 78 90<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;9<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;---------------<br>(20*3+q)*q&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/&nbsp; 3 34</p>
<p>我们看到q为5时(60+q)*q的值最接近334，而且不超过334。于是我们得到：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3&nbsp; 5<br>&nbsp;&nbsp;&nbsp; ---------------<br>&nbsp;&nbsp; / 12 34 56 78 90<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 9<br>&nbsp;&nbsp;&nbsp; ---------------<br>65 /&nbsp; 3 34<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3 25<br>&nbsp;&nbsp;&nbsp; ---------------<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 9 56</p>
<p>接下来就是重复上面的步骤了，这里就不再啰嗦了。 </p>
<p>这个手工算法其实和10进制关系不大，因此我们可以很容易的把它改为二进制，改为二进制之后，公式(3)就变成了：<br>q = (x^2 - 4*p^2)/(4*p+q) (4)</p>
<p>我们来看一个例子，计算100(二进制1100100)的开方：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp; 0&nbsp; 1&nbsp; 0<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -----------<br>&nbsp;&nbsp;&nbsp;&nbsp; / 1 10 01 00<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -----------<br>&nbsp;100 / 0 10 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0 00 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -----------<br>1001 /&nbsp;&nbsp; 10 01<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 10 01<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -----------<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0 00</p>
<p>这里每一步不再是把p乘以20了，而是把p乘以4，也就是把p右移两位，而由于q的值只能为0或者1，所以我们只需要判断余数(x^2 - 4*p^2)和(4*p+1)的大小关系，如果余数大于等于(4*p+q)那么该上一个1，否则该上一个0。</p>
<p>下面给出完成的C语言程序，其中root表示p，rem表示每步计算之后的余数，divisor表示(4*p+1)，通过a&gt;&gt;30取a的最高 2位，通过a&lt;&lt;=2将计算后的最高2位剔除。其中root的两次&lt;&lt;1相当于4*p。程序完全是按照手工计算改写的，应该不难理解。<br>unsigned short sqrt(unsigned long a){<br>&nbsp; unsigned long rem = 0;<br>&nbsp; unsigned long root = 0;<br>&nbsp; unsigned long divisor = 0;<br>&nbsp; for(int i=0; i&lt;16; ++i){<br>&nbsp;&nbsp;&nbsp; root &lt;&lt;= 1;<br>&nbsp;&nbsp;&nbsp; rem = ((rem &lt;&lt; 2) + (a &gt;&gt; 30));<br>&nbsp;&nbsp;&nbsp; a &lt;&lt;= 2;<br>&nbsp;&nbsp;&nbsp; divisor = (root&lt;&lt;1) + 1;<br>&nbsp;&nbsp;&nbsp; if(divisor &lt;= rem){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rem -= divisor;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; root++;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp; }<br>&nbsp; return (unsigned short)(root);<br>}</p>
<img src ="http://www.cppblog.com/QUIRE-0216/aggbug/41714.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/QUIRE-0216/" target="_blank">QUIRE-0216</a> 2008-01-23 14:21 <a href="http://www.cppblog.com/QUIRE-0216/archive/2008/01/23/41714.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>