<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>iPUNKID &#187; Programming</title>
	<atom:link href="http://blog.punkid.org/category/programming/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.punkid.org</link>
	<description>To ∞ and Beyond</description>
	<lastBuildDate>Sun, 29 Jan 2012 13:02:09 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Tips in Aggregate</title>
		<link>http://blog.punkid.org/2008/05/26/tips-in-aggregate/</link>
		<comments>http://blog.punkid.org/2008/05/26/tips-in-aggregate/#comments</comments>
		<pubDate>Mon, 26 May 2008 15:53:56 +0000</pubDate>
		<dc:creator>iPUNKID</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Wordpress]]></category>
		<category><![CDATA[English]]></category>
		<category><![CDATA[gentoo]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://blog.punkid.org/?p=216</guid>
		<description><![CDATA[都是些很零碎的tips，涉及到linux, wordpress, css, php, English &#8230; 选择性阅读吧! Douban and PHP 按照之前QQ签名秀的原理把豆瓣的个人广播系统也给提取出来了，效果请见此test页面。 使用方法是把以下代码添加到你的页面里: &#60;script type="text/javascript" src="http://punkid.org/glade/douban/request.php?userid=username&#38;numbers=5"&#62;&#60;/script&#62; 其中userid后面跟的是你的豆瓣用户名，numbers后面是显示条目数(最多10条)。至于怎么polish这个douban的miniblog纯粹是你的CSS活。对了，输出编码是UTF-8。 PHP tips: 用addslashes这个函数可以对字符串进行转义。 Linux 1. Tired of emerging the world? emerge $(eix -Iuc --format-compact "&#60;category&#62;/&#60;name&#62;" dev-libs/* &#124; head -n -1) 可以用来更新某一category(例如dev-libs)下的已安装软件。 2. Ape转mp3 emerge shntools 和 mac-port (gentoo-china overlay提供) 后运行: shnsplit -f filename.cue -t "%n - %t" -o "cust [...]]]></description>
			<content:encoded><![CDATA[<p>都是些很零碎的tips，涉及到linux, wordpress, css, php, English &#8230; 选择性阅读吧!</p>
<h3>Douban and PHP</h3>
<p>按照之前<a href="http://punkid.org/qqsign/" title="QQ签名秀">QQ签名秀</a>的原理把豆瓣的个人广播系统也给提取出来了，效果请见此<a href="http://punkid.org/glade/douban/test.html" title="Douban miniblog test page">test页面</a>。</p>
<p>使用方法是把以下代码添加到你的页面里:</p>
<pre lang="xml">
&lt;script type="text/javascript" src="http://punkid.org/glade/douban/request.php?userid=<strong>username</strong>&amp;numbers=5"&gt;&lt;/script&gt;
</pre>
<p>其中<code>userid</code>后面跟的是你的豆瓣用户名，<code>numbers</code>后面是显示条目数(最多10条)。至于怎么polish这个douban的miniblog纯粹是你的CSS活。对了，输出编码是UTF-8。</p>
<p>PHP tips: 用<a href="http://cn.php.net/manual/en/function.addslashes.php" title="PHP:addslashes">addslashes</a>这个函数可以对字符串进行转义。<br />
<span id="more-216"></span></p>
<h3>Linux</h3>
<h4>1. Tired of emerging the world?</h4>
<pre lang="bash">
emerge $(eix -Iuc --format-compact "&lt;category&gt;/&lt;name&gt;" dev-libs/* | head -n -1)
</pre>
<p>可以用来更新某一category(例如dev-libs)下的已安装软件。</p>
<h4>2. Ape转mp3</h4>
<p>emerge shntools 和 mac-port (<a href="http://code.google.com/p/gentoo-china-overlay/" title="Gentoo China Overlay">gentoo-china overlay</a>提供) 后运行:</p>
<pre lang="bash">
shnsplit -f filename.cue -t "%n - %t" -o "cust ext=mp3 lame --preset extreme - %f" filename.ape
</pre>
<p>会根据cue文件对ape进行切割成按<code>tracknumber - trackname</code>命名的mp3文件，不过ID3信息没法保存进去，交给<a href="http://www.musicbrainz.org/" title="Musicbrainz">Musicbrainz</a>搞定吧。</p>
<h4>3. 使用Aria2下载器</h4>
<p>原来用的axel不知何故在我的电脑上经常出现Initialing download就停滞不前的情况，无奈&#8230;换了个稍微大点的Aria2。顺便把Gentoo Mirror的默认下载也换成了aria2。更改make.conf如下:</p>
<pre lang="bash">
FETCHCOMMAND="/usr/bin/aria2c -c -s 4 -d ${DISTDIR} -o ${FILE} ${URI}"
RESUMECOMMAND="${FETCHCOMMAND}"
</pre>
<p>至于在firefox里用flashgot启用aria2下载，在<code>Executable path</code>里填<code>/usr/bin/rxvt</code> (任意虚拟终端，别用xterm就是了，那个启动太慢了)，然后在<code>Command line arguments template</code>里填<code>-e aria2c -s 5 -d [FOLDER] [URL]</code></p>
<h3>WordPress</h3>
<h4>1. 只显示当日评论数</h4>
<p>不明白我的意思的，留个言在到首页看下就知道了，当日有留言的日志会格外用类似于<em>3 comments today</em>方式显示。方法很简单，抽数据而已。修改你的模板的index.php，再最顶端添加:</p>
<pre lang="php">
&lt;?php
	$nowtime = current_time('timestamp');
	$today = date('Y-m-d G:i:s', mktime(0, 0, 0, date('m',$nowtime), date('d',$nowtime), date('Y',$nowtime)));
?&gt;
</pre>
<p>然后是修改loop部分:</p>
<pre lang="xml">
&lt;?php if (have_posts()) : ?&gt;
	&lt;?php while (have_posts()) : the_post(); ?&gt;

		<strong>&lt;?php $today_comments = $wpdb-&gt;get_var("SELECT COUNT(*) FROM $wpdb-&gt;comments WHERE comment_post_ID = $id AND comment_date &gt;= '$today' AND comment_approved = '1'"); ?&gt;</strong>
		&lt;div class="entry"
		&lt;h2 id="post-&lt;?php the_ID(); ?&gt;" class="entrytitle"&gt;&lt;a href="&lt;?php the_permalink() ?&gt;" rel="bookmark" title="Permanent Link to &lt;?php the_title(); ?&gt;"&gt;&lt;?php the_title(); ?&gt;&lt;/a&gt;&lt;/h2&gt;
		&lt;p class="metadata clearfix"&gt;
		<strong>&lt;span class="cmt"&gt;&lt;?php if ($today_comments &gt; 0) { ?&gt;&lt;a class="todaycmt" href="&lt;?php the_permalink() ?&gt;#comments" title="Comment on &lt;?php the_title(); ?&gt;"&gt;&lt;?php echo $today_comments; ?&gt; Comment&lt;?php if ($today_comments&gt;1) echo 's'; ?&gt; Today&lt;/a&gt;&lt;?php } else { ?&gt;&lt;?php comments_popup_link('No Comments', '1 Comment', '% Comments'); ?&gt;&lt;?php } ?&gt;&lt;/span&gt;</strong>
		&lt;/p&gt;
		...
		&lt;/div&gt;

		&lt;?php } ?&gt;

		...

&lt;?php endif; ?&gt;
</pre>
<p>加重部分是关键。</p>
<h4>2. 过滤某category的feed输出</h4>
<p>在模板的function.php里添加这段代码:</p>
<pre lang="php">
&lt;?php
function RssFilter($query) {
     if ($query-&gt;is_feed) {
         $query-&gt;set('cat','-<strong>22</strong>');
     }
         return $query;
}

add_filter('pre_get_posts','RssFilter');
?&gt;
</pre>
<p>其中22为你的category ID。</p>
<h3>CSS</h3>
<p>CSS的代码书写风格我倾向于单行式，用缩进表明元素的从属关系。例如:</p>
<pre lang="css">
#secondary div.modules {margin-bottom:40px;}
	#secondary div.modules a {color:#888;}
	#secondary div.modules a:hover {color:#FF32B3;text-decoration:underline;}
	#secondary div.modules h3 {color:#94C742;border-bottom:1px dotted #94C742;}
	#secondary div.modules ul li {padding:3px 8px;border-bottom:1px dashed #FF80D0;}
	#secondary div.modules ul li:hover {background:#F0F8E2;}

#bottom_wrapper h3 {color:#FDF262;border-bottom:1px solid #FDF262;}
	#bottom_wrapper div.modules {width:300px;margin:0 10px;float:left;position:relative;display:inline;}
	#bottom_wrapper div.modules ul li {height:1.6em;padding:3px 2px;border-bottom:1px dotted #528F08;overflow:hidden;}
	#bottom_wrapper div.modules ul li:hover {background:#528F08;}
	#bottom_wrapper div#misc table.calendar {width:300px;margin-bottom:20px;border-collapse:separate;border-spacing:1px;}
		table.calendar td {padding:3px 0 2px;text-align:center;}
		table.calendar td.calendar_h {display:none;}
		table.calendar td.today {background:#528F08;}
		table.calendar td.week {background:#528F08;color:#FDF262;}
	#bottom_wrapper div#tags ul li {margin-right:5px;padding:0;display:inline;border:0;}
		#bottom_wrapper div#tags ul li span, #bottom_wrapper div#tags div {display:none;}
</pre>
<p>也许这种单行的方式不利于阅读，但是类似block的书写方式最大的问题是一旦CSS代码上个几百行的，要找到某一行翻页是件很痛苦的事，而单行定义加上适当的缩进即便不看HTML源代码也能对页面结构有个基本的认识。还有就是&#8230;在VIM下用<code>w</code>,<code>b</code>进行整词跳跃是件很惬意的事，即便是单行也能很快的跳跃到需要修改查看的property。</p>
<h3>English</h3>
<h4>1. take with a pinch of salt</h4>
<p>Radiohead的<em>A Wolf at the Door</em>里有句歌词是<em>Take it with the love its given, take it with a pinch of salt, take it to the taxman</em>。</p>
<p>那<em>take it with a pinch of salt</em>真的是抓把盐吗? 真实的意思有点类似于姑且相信，半信半疑的意思，例如<em>Regarding what you said yesterday, I would take it with a pinch of salt</em>意思就是你昨天说的那些我姑且相信吧。</p>
<h4>Tia Dalma and I go way back</h4>
<p>在电影<em>Pirates of the Carribean : The Man&#8217;s Chest</em> (加勒比海盗2:聚魂棺)，Jack船长带着众人去找女巫Tia Dalma时说: <em>No worries, mates. Tia Dalma and I go way back.</em>。我记得当时我看的思路的版本翻译成了<em>伙计们，别担心，Tia Dalma和我待会就回来</em>。这其实是错误的，<em>go back way</em>的意思是表示两人认识很久了，交情很好。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.punkid.org/2008/05/26/tips-in-aggregate/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>利用牛顿迭代法求平方根</title>
		<link>http://blog.punkid.org/2008/02/28/compute-the-square-root-via-newtons-iteration/</link>
		<comments>http://blog.punkid.org/2008/02/28/compute-the-square-root-via-newtons-iteration/#comments</comments>
		<pubDate>Thu, 28 Feb 2008 13:57:48 +0000</pubDate>
		<dc:creator>iPUNKID</dc:creator>
				<category><![CDATA[Mathematics]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[Newton's Iteration]]></category>

		<guid isPermaLink="false">http://blog.punkid.org/2008/02/28/compute-the-square-root-via-newtons-iteration/</guid>
		<description><![CDATA[昨天查mathomatic的MAN时看到一个很有意思的计算平方根的方法(当然不是叫你在Excel里n^1/2啦!): 求n的平方根，先假设一猜测值X0 = 1，然后根据以下公式求出X1，再将X1代入公式右边，继续求出X2&#8230;通过有效次迭代后即可求出n的平方根，Xk+1 先让我们来验证下这个巧妙的方法准确性，来算下2的平方根 (Computed by Mathomatic) 1-> x_new = ( x_old + y/x_old )/2 y (x_old + -----) x_old #1: x_new = --------------- 2 1-> calculate x_old 1 Enter y: 2 Enter initial x_old: 1 x_new = 1.5 1-> calculate x_old 2 Enter y: 2 Enter initial x_old: 1 x_new = 1.4166666666667 1-> [...]]]></description>
			<content:encoded><![CDATA[<p>昨天查mathomatic的<a href="http://www.mathomatic.com/math/doc/am.html#calculate" title="Mathomatic Command Reference: Calculate command">MAN</a>时看到一个很有意思的计算平方根的方法(当然不是叫你在Excel里n^1/2啦!):</p>
<p>求n的平方根，先假设一猜测值<code class="math">X<sub>0</sub> = 1</code>，然后根据以下公式求出<code class="math">X<sub>1</sub></code>，再将<code class="math">X<sub>1</sub></code>代入公式右边，继续求出<code class="math">X<sub>2</sub></code>&#8230;通过有效次迭代后即可求出n的平方根，<code class="math">X<sub>k+1</sub></code></p>
<p class="center"><img src="http://pic.yupoo.com/punkid/5286852a16f4/chsf3aqv.jpg" alt=" x_(k+1)=1/2(x_k+n/(x_k))" width="111" height="37" border="0" /></p>
<p>先让我们来验证下这个巧妙的方法准确性，来算下2的平方根 (Computed by Mathomatic)<br />
<span id="more-198"></span></p>
<pre>
1-> x_new = ( x_old + y/x_old )/2

                       y
            (x_old + -----)
                     x_old
#1: x_new = ---------------
                   2

1-> calculate x_old 1
Enter y: 2
Enter initial x_old: 1

<strong class="red"> x_new = 1.5</strong>

1-> calculate x_old 2
Enter y: 2
Enter initial x_old: 1

<strong class="red"> x_new = 1.4166666666667</strong>

1-> calculate x_old 3
Enter y: 2
Enter initial x_old: 1

<strong class="red"> x_new = 1.4142156862745</strong>

1-> calculate x_old 10
Enter y: 2
Enter initial x_old: 1
Convergence reached after 6 iterations.

<strong class="red"> x_new = 1.4142135623731</strong>
...
</pre>
<p>可见，随着迭代次数的增加，运算值会愈发接近真实值。很神奇的算法，可是怎么来的呢? 查了下<a href="http://en.wikipedia.org/wiki/Newton%27s_method" title="Wikipedia: Newton's method">wikipedia</a>和<a href="http://mathworld.wolfram.com/NewtonsIteration.html" title="Wolfram: Newton's Iteration">wolfram</a>，原来算法的名字叫Newton&#8217;s Iteration (牛顿迭代法)。</p>
<p>下面是极其<span lang="ja" xml:lang="ja">つまらない</span>(boring)的数理介绍，不喜欢数学的言下之意也就是绝大部分人可以略过了。</p>
<h3>简单推导</h3>
<p>假设<code class="math">f(x)</code>是关于<code class="math">X</code>的函数:</p>
<p><img src="http://pic.yupoo.com/punkid/1773352a25d8/9lcgjzet.jpg" alt="An illustration of one iteration of Newton's method" width="300" height="247" border="0" /></p>
<p>求出<code class="math">f(x)</code>的一阶导，即斜率:</p>
<p class="center"><img src="http://pic.yupoo.com/punkid/1847652a26a3/zcbz5a4b.jpg" width="409" height="48" border="0" alt="f'(x_{n}) = \frac{ \mathrm{rise} }{ \mathrm{run} } = \frac{ \mathrm{\Delta y} }{ \mathrm{\Delta x} } = \frac{ f( x_{n} ) - 0 }{ x_{n} - x_{n+1} } = \frac{0 - f(x_{n})}{(x_{n+1} - x_{n})}\,\!" /></p>
<p>简化等式得到:</p>
<p class="center"><img width="108" height="37" border="0" alt=" x_(n+1)=x_n-(f(x_n))/(f^'(x_n)) " src="http://pic.yupoo.com/punkid/0290752a2462/t4yu9w45.jpg"/></p>
<p>然后利用得到的最终式进行迭代运算直至求到一个比较精确的满意值，为什么可以用迭代法呢?理由是中值定理(Intermediate Value Theorem):</p>
<blockquote><p>
如果<code class="math">f</code>函数在闭区间<code class="math">[a,b]</code>内连续，必存在一点<code class="math">x</code>使得<code class="math">f(x) = c</code>，<code class="math">c</code>是函数<code class="math">f</code>在闭区间<code class="math">[a,b]</code>内的一点
</p></blockquote>
<p>我们先猜测一<code class="math">X</code>初始值，例如1，当然地球人都知道除了1本身之外任何数的平方根都不会是1。然后代入初始值，通过迭代运算不断推进，逐步靠近精确值，直到得到我们主观认为比较满意的值为止。例如要求768的平方根，因为<code class="math">25<sup>2</sup> = 625</code>，而<code class="math">30<sup>2</sup> = 900</code>，我们可先代入一猜测值26，然后迭代运算，得到较精确值:27.7128。</p>
<p>回到我们最开始的那个&#8221;莫名其妙&#8221;的公式，我们要求的是<code class="math">N</code>的平方根，令<code class="math">x<sup>2</sup> = n</code>，假设一关于<code class="math">X</code>的函数<code class="math">f(x)</code>为:</p>
<p class="center"><code class="math">f(X) = X<sup>2</sup> - n</code></p>
<p>求<code class="math">f(X)</code>的一阶导为:</p>
<p class="center"><code class="math">f'(X) = 2X</code></p>
<p>代入前面求到的最终式中:</p>
<p class="center"><code class="math">X<sub>k+1</sub> = X<sub>k</sub> - (X<sub>k</sub><sup>2</sup> - n)/2X<sub>k</sub></code></p>
<p>化简即得到我们最初提到的那个求平方根的神奇公式了:</p>
<p class="center"><img src="http://pic.yupoo.com/punkid/5286852a16f4/chsf3aqv.jpg" alt=" x_(k+1)=1/2(x_k+n/(x_k))" width="111" height="37" border="0" /></p>
<h3>用泰勒公式推导</h3>
<p>我之前介绍过在<em>The Art and Science of C</em>一书中有用到<a href="http://blog.punkid.org/2007/07/19/the-art-and-science-of-c-note-two/" title="The Art and Science of C  阅读笔记 II">泰勒公式求平方根的算法</a>，其实牛顿迭代法也可以看作是泰勒公式(Taylor Series)的简化，先回顾下泰勒公式:</p>
<p class="center"><img src="http://pic.yupoo.com/punkid/1697952a1ea6/0k7gu191.jpg" alt="f(x_0+epsilon)=f(x_0)+f^'(x_0)epsilon+1/2f^('')(x_0)epsilon^2+.... " width="269" height="23" border="0" /></p>
<p>仅保留等式右边前两项:</p>
<p class="center"><img src="http://pic.yupoo.com/punkid/5762152a1f4e/y8nndhdy.jpg" alt="f(x_0+epsilon) approx f(x_0)+f^'(x_0)epsilon." width="160" height="16" border="0" /></p>
<p>令<code class="math">f(X<sub>0</sub>+&epsilon;) = 0</code>，得到:</p>
<p class="center"><img src="http://pic.yupoo.com/punkid/3476952a2106/n7gfjyvw.jpg" alt="epsilon_0=-(f(x_0))/(f^'(x_0))" width="82" height="37" border="0" /></p>
<p>再令<code class="math">X<sub>1</sub> = X<sub>0</sub> + &epsilon;<sub>0</sub></code>，得到<code class="math">&epsilon;<sub>1</sub></code>&#8230;依此类推可知:</p>
<p class="center"><img src="http://pic.yupoo.com/punkid/3903852a21fb/kwl644nf.jpg" alt="epsilon_n=-(f(x_n))/(f^'(x_n))" width="82" height="37" border="0" /></p>
<p>转化为:</p>
<p class="center"><img width="108" height="37" border="0" alt=" x_(n+1)=x_n-(f(x_n))/(f^'(x_n)) " src="http://pic.yupoo.com/punkid/0290752a2462/t4yu9w45.jpg"/></p>
<h3>引申</h3>
<p>从推导来看，其实牛顿迭代法不仅可以用来求平方根，还可以求立方根，甚至更复杂的运算。</p>
<p>同样，我们还可以利用C语言来实现下那个最简单的求平方根的公式(尽管我们可以直接用<code>sqrt()</code>完成)</p>
<pre>
#include &lt;stdio.h&gt;
#include &lt;math.h&gt;

#define N 768

main() {
        float x=1;
        int i;
        for (i=1;i&lt;=1000;i++) {  // recursion times : 1000
                x = (x + N/x)/2;
        }
        printf("The square root of %d is %f\n",N,x);
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.punkid.org/2008/02/28/compute-the-square-root-via-newtons-iteration/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Linear Least Squares</title>
		<link>http://blog.punkid.org/2007/12/20/linear-least-squares/</link>
		<comments>http://blog.punkid.org/2007/12/20/linear-least-squares/#comments</comments>
		<pubDate>Thu, 20 Dec 2007 06:26:33 +0000</pubDate>
		<dc:creator>iPUNKID</dc:creator>
				<category><![CDATA[Mathematics]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[LLS]]></category>
		<category><![CDATA[OLS]]></category>

		<guid isPermaLink="false">http://blog.punkid.org/2007/12/20/linear-least-squares/</guid>
		<description><![CDATA[纯粹大学高等数学，还附带一个C程序&#8230;已感不适者请略过，go to an interesting fashion trend magazine :D 注: 此文章前半部分翻译自wikipedia这个墙外之物。 Linear Least Squares (线性最小二乘法，以下简称LLS)，是解决线性回归问题的重要方法之一，常常用来求解等式多于变量情况下的最优线性方程。特别是在统计学中，常常需要根据一组数据(例如时间序列数据)来模拟其自变量与因变量之间的线性关系，用最小二乘法可以很好的拟合数据，消除残差的不确定性带来的影响。 理论 假设我们要求出关于的方程 A是一个m行n列矩阵，而x是未知的n阶向量，b是已知的m阶向量。利用最小二乘法原理，列出最小化残差等式: 其中 [Ax]i表示第i 阶向量Ax。因为矩阵 v2 = vTv，vT为v的转秩，得出: 因为bT(Ax) = (Ax)Tb，对等式求x的偏导: 得到: 左边的ATA是个n行n列矩阵，如果A矩阵满秩的话，可得出: 其中(ATA)-1AT是A的伪逆矩阵，因为矩阵A的逆矩阵A-1不存在，因为m&#8800;n。 实例 假设存在四组坐标点(0, 3), (2, 3), (4, 4), (−1, 2)，要求出关于&#945;x + &#946; = y的线性方程，可将其方程变换为矩阵形式: 矩阵A (即 (X 1) )可以表示为 向量b (即 Y)可以表示为 得出: 最后可知: 152/59 + 20/59x= [...]]]></description>
			<content:encoded><![CDATA[<p>纯粹大学高等数学，还附带一个C程序&#8230;已感不适者请略过，go to an interesting fashion trend magazine :D</p>
<p>注: 此文章前半部分翻译自<a href="http://en.wikipedia.org/wiki/Linear_least_squares" title="Linear least squares">wikipedia</a>这个墙外之物。</p>
<p><strong>Linear Least Squares</strong> (线性最小二乘法，以下简称LLS)，是解决线性回归问题的重要方法之一，常常用来求解等式多于变量情况下的最优线性方程。特别是在统计学中，常常需要根据一组数据(例如时间序列数据)来模拟其自变量与因变量之间的线性关系，用最小二乘法可以很好的拟合数据，消除残差的不确定性带来的影响。<br />
<span id="more-185"></span></p>
<h3>理论</h3>
<p>假设我们要求出关于<img src="http://photo14.yupoo.com/20071220/115905_644626589_pdvqvhvx.jpg" alt="X" width="12" height="15" border="0" />的方程</p>
<p><img src="http://photo15.yupoo.com/20071220/114452_1712083561_fxwdiash.jpg" alt="1" width="69" height="19" border="0" /></p>
<p><span class="math">A</span>是一个m行n列矩阵，而<span class="math">x</span>是未知的n阶向量，<span class="math">b</span>是已知的m阶向量。利用最小二乘法原理，列出最小化残差等式:</p>
<p><img src="http://photo14.yupoo.com/20071220/114453_7593697.jpg" alt="2" width="500" height="23" border="0" /></p>
<p>其中<br />
<span class="math">[Ax]<sub>i</sub></span>表示第i 阶向量<span class="math">Ax</span>。因为矩阵 <span class="math">v<sup>2</sup> = v<sup>T</sup>v</span>，<span class="math">v<sup>T</sup></span>为<span class="math">v</span>的转秩，得出:</p>
<p><img src="http://photo15.yupoo.com/20071220/114453_2052200075.jpg" alt="3" width="500" height="23" border="0" /></p>
<p>因为<span class="math">b<sup>T</sup>(Ax) = (Ax)<sup>T</sup>b</span>，对等式求<span class="math">x</span>的偏导:</p>
<p><img src="http://photo15.yupoo.com/20071220/114453_1518467607_hoxvrbla.jpg" alt="4" width="499" height="42" border="0" /></p>
<p>得到:</p>
<p><img src="http://photo15.yupoo.com/20071220/114453_199969305_zvldehak.jpg" alt="5" width="122" height="20" border="0" /></p>
<p>左边的<span class="math">A<sup>T</sup>A</span>是个n行n列矩阵，如果<span class="math">A</span>矩阵满秩的话，可得出:</p>
<p><img src="http://photo15.yupoo.com/20071220/114454_64194210_avwwhfbb.jpg" alt="6" width="157" height="25" border="0" /></p>
<p>其中<span class="math">(A<sup>T</sup>A)<sup>-1</sup>A<sup>T</sup></span>是<span class="math">A</span>的伪逆矩阵，因为矩阵<span class="math">A</span>的逆矩阵<span class="math">A<sup>-1</sup></span>不存在，因为<span class="math">m&ne;n</span>。</p>
<h3>实例</h3>
<p>假设存在四组坐标点(0, 3), (2, 3), (4, 4), (−1, 2)，要求出关于<span class="math">&alpha;x + &beta; = y</span>的线性方程，可将其方程变换为矩阵形式:</p>
<p><img src="http://photo14.yupoo.com/20071220/114454_352410762_choqppxn.jpg" alt="7" width="138" height="52" border="0" /></p>
<p>矩阵<span class="math">A (即 (X 1) )</span>可以表示为</p>
<p><img src="http://photo15.yupoo.com/20071220/114454_1407408024_cppudlxb.jpg" alt="8" width="130" height="98" border="0" /></p>
<p>向量<span class="math">b (即 Y)</span>可以表示为</p>
<p><img src="http://photo14.yupoo.com/20071220/114454_1233267008_oickasxx.jpg" alt="9" width="87" height="98" border="0" /></p>
<p>得出:</p>
<p><img src="http://photo15.yupoo.com/20071220/114452_737794899_bmnvmmka.jpg" alt="10" width="190" height="52" border="0" /></p>
<p><img src="http://photo14.yupoo.com/20071220/135306_1787093503_foipdvvi.jpg" alt="14" width="117" height="52" border="0" /></p>
<p><img src="http://photo14.yupoo.com/20071220/135306_467402935_zfrhxpil.jpg" alt="15" width="145" height="52" border="0" /></p>
<p><img src="http://photo15.yupoo.com/20071220/135306_1711046085_hdjoihes.jpg" alt="16" width="223" height="52" border="0" /></p>
<p><img src="http://photo14.yupoo.com/20071220/114452_2078797515_cvgjpulr.jpg" alt="11" width="150" height="52" border="0" /></p>
<p><img src="http://photo14.yupoo.com/20071220/135544_964450516_uukatkos.jpg" alt="17" width="197" height="52" border="0" /></p>
<p><img src="http://photo15.yupoo.com/20071220/114452_137783562_xfxwutgd.jpg" alt="12" width="353" height="52" border="0" /></p>
<p>最后可知:</p>
<p><span class="math"><sup>152</sup>/<sub>59</sub> + <sup>20</sup>/<sub>59</sub>x= y</span> 是最优线性解</p>
<p>其结果与用<abbr title="Ordinary Least Square">OLS</abbr>(一般最小二乘法)得到的解是一致的，有兴趣的朋友可以用我写的这个C程序(<code>OLS.c</code>)来验证下结果:</p>
<pre>
#include <stdio.h>
#include "math.h"

/*
 * Function : average
 * Usage: average(x,n);
 * -------------------------------
 * Description: Returns the average of an array.
 */

static float average(float a[],int n){
        float sum=0;
        int i;
        for (i=0;i&lt;n;i++)
        {
                sum+=a[i];
        }
        return (sum/n);
}

/*
 * Function : Main
 * -------------------------------
 * Description: Calcuate the Simple Linear Regression's estimates using OLS
 */

main() {
        int n,i;
        float sumX=0,sumY=0,numerator=0,denominator=0;
        float beta0,beta1,averageX,averageY,x[100],y[100];
        printf("How many observations do you want to type in?\n");
        scanf("%d",&#038;n);

        printf("Please type in the observations\n");
        for (i=0;i&lt;n;i++)
        {
                scanf("%f",&#038;x[i]);
        }

        /*Compute the average of X observations*/
        averageX=average(x,n);

        printf("Please type in the results\n");
        for (i=0;i&lt;n;i++)
        {
                scanf("%f",&#038;y[i]);
        }

        /*Compute the average of Y results*/
        averageY=average(y,n);

        /*Calculate the sum of (X[i]-averageX)*(Y[i]-averageY)*/
        for (i=0;i&lt;n;i++)
        {
                numerator+=((x[i]-averageX)*(y[i]-averageY));
        }
        printf("The numerator is %.4f\n",numerator);

        /*Calculate the sum of (X[i]-averageX)^2*/
        for (i=0;i&lt;n;i++)
        {
                denominator+=((x[i]-averageX)*(x[i]-averageX));
        }
        printf("The denominator is %.4f\n",denominator);

        /*Compute and print out the slope estimate : &beta;1*/
        beta1=numerator/denominator;
        printf("The slope estimate &beta;1 is %.4f\n",beta1);

        /*Compute and print out the intercept estimate : &beta;0*/
        beta0=averageY-beta1*averageX;
        printf("The intercept estimate &beta;0 is %.4f\n",beta0);

        /*Now we can print out the equation obtained from the samples*/
        printf("Y = %.4f + %.4fX\n",beta0,beta1);
}
</pre>
<p>程序先需要经过编译才能运行，执行后先填入观察相数目(自变量)，再分别填入自变量与因变量的数据就行了。</p>
<h3>用途</h3>
<p>LLS可以用来求一个上市公司的&beta;系数估计值，&beta;系数在金融界中已经被广泛应用于刻画公司业绩与总体市场行为的关系，那些倾向于高杠杆而与总体市场联系紧密的往往具有较大的&beta;值，而低风险保守的公司&beta;往往比较小。例如一个&beta;系数为2.0的公司，如果总体市场的预期收益率为5%，则该公司的预期收益率为10%，反之亦然，如果总体市场预期收益率下降了5%，则该公司预期收益率下降10%，而如果&beta;值为负数时则呈现负相关关系。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.punkid.org/2007/12/20/linear-least-squares/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Blogbus Hack 2 :  打造Tag Clouds效果</title>
		<link>http://blog.punkid.org/2007/11/17/blogbus-hack-2-generate-tag-clouds/</link>
		<comments>http://blog.punkid.org/2007/11/17/blogbus-hack-2-generate-tag-clouds/#comments</comments>
		<pubDate>Sat, 17 Nov 2007 08:23:47 +0000</pubDate>
		<dc:creator>iPUNKID</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[hack]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[My Projects]]></category>
		<category><![CDATA[tag]]></category>
		<category><![CDATA[Tag Clouds]]></category>

		<guid isPermaLink="false">http://blog.punkid.org/2007/11/17/blogbus-hack-2-generate-tag-clouds/</guid>
		<description><![CDATA[最近在弄个blogbus的模板，折腾了几天，难产again&#8230;暂时性转移到另一个idea上来，给blogbus的tags输出做成tag clouds(标签云)效果。什么是Tag呢? 自己去看blogbus的help吧。什么是Tag Clouds呢? 请看下面这个效果图，tag文字大小依据使用频率多少区分开来，使用Tag Clouds可以更清楚的传达what&#8217;s your blog all about，更多的信息看SmashingMagazine的这篇文章Tag Clouds Gallery: Examples And Good Practices吧。 Blogbus的tag输出方式是固定的，排列顺序由使用最多的到使用最少的，你可以设定显示tag的数目，为了更好的Tag Clouds效果，建议设置显示数目大点(太大了，也不是件好事，至于为什么，我待会再说)。正是因为Blogbus的封装处理，要hack这种Tag Clouds效果只能从javascript+CSS入手了 (注:此hack不适用于旧版blogbus模板系统) JAVASCRIPT部分 &#60;script type="text/javascript"&#62; function tagClouds(id, maxsize, minsize) { if (!document.getElementById &#124;&#124; !document.getElementsByTagName) return; if (!document.getElementById(id)) return; var taglist = document.getElementById(id); var tag = taglist.getElementsByTagName('li'); var maxcount = parseInt(tag[0].getElementsByTagName('span')[0].firstChild.nodeValue.substring(1,3)); var mincount = parseInt(tag[tag.length-1].getElementsByTagName('span')[0].firstChild.nodeValue.substring(1,3)); var offset = [...]]]></description>
			<content:encoded><![CDATA[<p>最近在弄个blogbus的模板，折腾了几天，难产again&#8230;暂时性转移到另一个idea上来，给blogbus的tags输出做成tag clouds(标签云)效果。什么是Tag呢? 自己去看blogbus的help吧。什么是Tag Clouds呢? 请看下面这个效果图，tag文字大小依据使用频率多少区分开来，使用Tag Clouds可以更清楚的传达what&#8217;s your blog all about，更多的信息看SmashingMagazine的这篇文章<a href="http://www.smashingmagazine.com/2007/11/07/tag-clouds-gallery-examples-and-good-practices/" title="Tag Clouds Gallery: Examples And Good Practices">Tag Clouds Gallery: Examples And Good Practices</a>吧。</p>
<p><img src="http://photo11.yupoo.com/20071115/230557_371638314_hywwvibq.jpg" alt="wptags" width="450" height="192" border="0" /></p>
<p>Blogbus的tag输出方式是固定的，排列顺序由使用最多的到使用最少的，你可以设定显示tag的数目，为了更好的Tag Clouds效果，建议设置显示数目大点(太大了，也不是件好事，至于为什么，我待会再说)。正是因为Blogbus的封装处理，要hack这种Tag Clouds效果只能从javascript+CSS入手了 (<strong>注</strong>:此hack不适用于旧版blogbus模板系统)<br />
<span id="more-171"></span></p>
<h3>JAVASCRIPT部分</h3>
<pre>
&lt;script type="text/javascript"&gt;
function tagClouds(id, maxsize, minsize) {
        if (!document.getElementById || !document.getElementsByTagName) return;
        if (!document.getElementById(id)) return;

        var taglist = document.getElementById(id);
        var tag = taglist.getElementsByTagName('li');
        var maxcount = parseInt(tag[0].getElementsByTagName('span')[0].firstChild.nodeValue.substring(1,3));
        var mincount = parseInt(tag[tag.length-1].getElementsByTagName('span')[0].firstChild.nodeValue.substring(1,3));
        var offset = (maxsize-minsize)/(maxcount-mincount);

        for (var i=0;i&lt;tag.length;i++) {
                var count = parseInt(tag[i].getElementsByTagName('span')[0].firstChild.nodeValue.substring(1,3));
                var weight = (count-mincount)*offset+minsize;
                tag[i].getElementsByTagName('a')[0].style.fontSize = weight+'em';
        };
}

window.onload = function() {
        tagClouds('tags', 2.2, 1);
        //<strong>2.2</strong> 和 <strong>1</strong> 分别为TagClouds的最大字号与最小字号值，<strong>2.2</strong>表示是普通字号的2.2倍
}
&lt;/script&gt;
</pre>
<p>上面这段代码加哪的话你还是看我第一篇<a href="http://blog.punkid.org/2007/11/04/blogbus-hack-save-the-commentform-user-info-revised/" title="Blogbus Hack : 保存评论框信息 (更新GreaseMonkey脚本)">hack</a>吧。补充一点，如果你也用了我那个&#8221;保存评论框信息&#8221;的脚本的话，你可以把这两段代码都放到一个<code>&lt;script type="text/javascript"&gt; ... &lt;/script&gt;</code>中间，两段<code>window.onload</code>可以合并为如下格式，并放到代码的最后面。</p>
<pre>
window.onload = function() {
        tagClouds('tags', 2.2, 1);
        rememberFormInputs('commentForm','input_',120); //另一个脚本程序
}
</pre>
<h3>CSS部分</h3>
<p>将以下代码加入到blogbus模板里的CSS处:</p>
<pre>
#tags ul li {display:inline;margin-left:6px;}

#tags ul li span{display:none;} /*如果你不希望显示诸如[36]的tag使用次数的话*/
</pre>
<h3>HACK说明</h3>
<h4>hack思路解释</h4>
<p>因为是hack，不是tutorial，我只说下前面那段javascript的思路就是了。求出最大使用频率tag与最小使用频率tag之间的使用数差值，然后通过你所设置的<code>maxsize</code>和<code>minsize</code>之差除以tag使用数差值求得位移量。利用for循环来算出每个tag比最小使用频率tag的位移量多多少，再赋予CSS中的<code>font-size</code>属性，实现字号的不同。</p>
<p>其中要注意的是，因为我用的是<code>parseInt(*.substring(1,3))</code>，意思是从那个类似于<code>[36]</code>的使用频率中截取出数字来，再把<code>string</code>转化为<code>int</code>型。也就是说，如果你自定义了<code>[36]</code>的显示方式为其他的，就可能需要重新调整<code>substring(1,3)</code>中的两个value了，<code>substring</code>的意思是截取第i+1个字符到第j个字符。例如你自定义的显示方式是<code>||36||</code>的话，那需要截取的是第3，第4个字符，<code>substring(1,3)</code>相应调整为<code>substring(2,4)</code>。</p>
<p>CSS中定义的<code>#tags ul li {display:inline;}</code>是为了实现横排，因为<code>li</code>默认是<code>block</code>级别，每一个<code>li</code>占了一行，而<code>inline</code>值只会占据其内容宽度。</p>
<p>你可以自己更改<code>window.onload() ...</code>中<code>tagClouds('tags', 2.2, 1)</code>后面的两个数值大小，它们一个是最大字号，一个是最小字号。我在javascript里设置的<code>font-size</code>用的是<code>em</code>单位，而不是<code>px</code>，因为<code>em</code>比<code>px</code>在字号控制上灵活的多。用<code>px</code>的话，我们只能设置整数值，而<code>em</code>的话，它其实是当前普通字号的倍数值，例如默认的<code>li</code>字号可能是12px，那么一个较大使用频率的tag，它的字号倍数是1.9的话，相应的大小就是12px*1.9=22.8px了，比起直接使用<code>px</code>灵活的多。我的blog上字号设置用的就都是<code>em</code> !</p>
<h4>The Downside of this Script</h4>
<p>正如我刚才说的，Tag的显示条目数并非越大越好，因为每增加一个tag显示条目数，就意味着程序要多运算一次。而Javascript的运算负担是完全由客户端来承担的，假如你用上千个tag，你把它们都显示出来的话，那浏览者在看你的页面时，光是载入运算那个javascript就要花上不少时间，一般来说，数十个tag还是可以接受的，别忘了电脑的运算速度比人脑快哦!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.punkid.org/2007/11/17/blogbus-hack-2-generate-tag-clouds/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Blogbus Hack : 保存评论框信息 (更新GreaseMonkey脚本)</title>
		<link>http://blog.punkid.org/2007/11/04/blogbus-hack-save-the-commentform-user-info-revised/</link>
		<comments>http://blog.punkid.org/2007/11/04/blogbus-hack-save-the-commentform-user-info-revised/#comments</comments>
		<pubDate>Sun, 04 Nov 2007 07:40:24 +0000</pubDate>
		<dc:creator>iPUNKID</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[cookie]]></category>
		<category><![CDATA[Firefox]]></category>
		<category><![CDATA[GreaseMonkey]]></category>
		<category><![CDATA[hack]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[My Projects]]></category>
		<category><![CDATA[保存评论框信息]]></category>

		<guid isPermaLink="false">http://blog.punkid.org/2007/11/04/blogbus-hack-save-the-commentform-user-info/</guid>
		<description><![CDATA[Blogbus的评论系统有两点让我极为不爽: 一是评论过滤机制，导致我的留言经常莫名其妙的被拒绝发表(我连双脚都举起来保证我绝对没有发表任何有违和谐的信息)；二是评论框不会在提交留言之后记录我的用户信息(Name, E-Mail, URL)，每次留言我都得手动填写。这前一点不爽的谁也没办法，谁叫我们要和谐呢，后面这点的话我们可以通过在模板里加入一段javascript来保存评论者的cookie信息。我得先申明，对Javascript我也基本属于入门阶段，以下代码中很大程度参考自PPK的这篇文章Javascript &#8211; Cookies。 Blogbus最近改版一次后，新的模板系统不再允许修改评论框了，所有模板的评论框都是统一规范的，所以这个脚本适用于任何新版模板系统的任何模板，旧版的话我稍后补充。对于新版模板的话，你需要做的只是在header(前提是你先的启用自定义模板来修改)里加入以下代码: &#60;script type=&#34;text/javascript&#34;&#62; function setCookie(name,value,days) { if(days) { var date = new Date(); date.setTime(date.getTime()+(days*24*60*60*1000)); var expires = ";expires="+date.toGMTString(); } else var expires = ""; document.cookie = name+"="+value+expires+"; path=/"; } function getCookie(name) { var nameEQ = name + "="; var ca = document.cookie.split(';'); for(var i=0;i &#60; ca.length;i++) { var c [...]]]></description>
			<content:encoded><![CDATA[<p>Blogbus的评论系统有两点让我极为不爽: 一是评论过滤机制，导致我的留言经常莫名其妙的被拒绝发表(我连双脚都举起来保证我绝对没有发表任何有违和谐的信息)；二是评论框不会在提交留言之后记录我的用户信息(Name, E-Mail, URL)，每次留言我都得手动填写。这前一点不爽的谁也没办法，谁叫我们要和谐呢，后面这点的话我们可以通过在模板里加入一段javascript来保存评论者的cookie信息。我得先申明，对Javascript我也基本属于入门阶段，以下代码中很大程度参考自PPK的这篇文章<a href="http://www.quirksmode.org/js/cookies.html" title="Javascript - Cookies">Javascript &#8211; Cookies</a>。</p>
<p>Blogbus最近改版一次后，新的模板系统不再允许修改评论框了，所有模板的评论框都是统一规范的，所以这个脚本适用于任何新版模板系统的任何模板，旧版的话我稍后补充。对于新版模板的话，你需要做的只是在<em>header</em>(前提是你先的启用自定义模板来修改)里加入以下代码:<br />
<span id="more-164"></span></p>
<pre>
&lt;script type=&quot;text/javascript&quot;&gt;
function setCookie(name,value,days) {
        if(days) {
                var date = new Date();
                date.setTime(date.getTime()+(days*24*60*60*1000));
                var expires = ";expires="+date.toGMTString();
        }
        else var expires = "";
        document.cookie = name+"="+value+expires+"; path=/";
}

function getCookie(name) {
        var nameEQ = name + "=";
        var ca = document.cookie.split(';');
        for(var i=0;i &lt; ca.length;i++) {
                var c = ca[i];
                while (c.charAt(0)==' ') c = c.substring(1,c.length);
                if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
        }
        return null;
}

function rememberFormInputs(form_id, prefix, days) {
        if(!document.getElementById(form_id)) return false;
        var form = document.getElementById(form_id);
        var inputs = form.getElementsByTagName('input');
        for (var i=0; i&lt;inputs.length; i++) {
                var input = inputs.item(i);
                if (input.type == 'text') {
                        input.onblur = function() {
                                var name = this.name;
                                var value = this.value;
                                setCookie(prefix + name, value, days);
                        };
                        var old_value = getCookie(prefix + input.name);
                        if (old_value &amp;&amp; old_value !='') {
                                input.value = old_value;
                        }
                }
        }
}

window.onload = function() {
        rememberFormInputs('commentForm','input_',120); //保存用户信息120天，你可以设置为更久
}
&lt;/script&gt;
</pre>
<p>对于使用旧版模板系统的，因为模板的不同，并不能保证所有留言框都有名为<em>commentForm</em>的<code>ID</code>，你需要修改自定义模板里的<em>Comment.Form</em>模块，其中有这么一句:</p>
<pre>&lt;form method=&quot;post&quot; action=&quot;&lt;!-- ~ addcomment_url ~ --&gt;&quot; /&gt;</pre>
<p>修改为:</p>
<pre>&lt;form method=&quot;post&quot; action=&quot;&lt;!-- ~ addcomment_url ~ --&gt;&quot; id=&quot;commentForm&quot; /&gt;</pre>
<p>然后在<em>header</em>里的&lt;/head&gt;之上照旧添加上面那段代码就是了。</p>
<p>至于那段代码什么意思，我也懒的解释了，懂一点javascript的都能看懂，不懂的知道怎么用就行了 :D Keep in mind, this is NOT a tutorial, but a little hack</p>
<p><strong class="red">更新:</strong> 刚写了个<a href="https://addons.mozilla.org/en-US/firefox/addon/748" title="Grease Monkey">GreaseMonkey</a>小脚本，如果你装了Firefox和这个插件的话，再装上我这个脚本程序，以后无论你所访问的blogbus博客有没有添加我上面的那段script，使用的是新模板系统还是旧的，都能通过这个脚本程序保存你的信息。</p>
<p>脚本下载地址 : <a href="http://punkid.org/glade/greasemonkey/rememberTheName.user.js" title="GreaseMonkey script on Blogbus commentform">rememberTheName.user.js</a> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.punkid.org/2007/11/04/blogbus-hack-save-the-commentform-user-info-revised/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>QQ签名秀 : 在你的blog里调用QQ签名</title>
		<link>http://blog.punkid.org/2007/10/21/show-your-qq-signatures-in-blog/</link>
		<comments>http://blog.punkid.org/2007/10/21/show-your-qq-signatures-in-blog/#comments</comments>
		<pubDate>Sat, 20 Oct 2007 18:05:10 +0000</pubDate>
		<dc:creator>iPUNKID</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[QQ签名秀]]></category>
		<category><![CDATA[xml]]></category>
		<category><![CDATA[在Blog中调用QQ签名]]></category>

		<guid isPermaLink="false">http://blog.punkid.org/2007/10/21/show-your-qq-signatures-in-blog/</guid>
		<description><![CDATA[在上篇日志里我就提到要写一个输出QQ签名的程序了，作用是仅仅通过插入一行类似于豆瓣秀的代码在任意页面上显示最新的QQ签名，有点类似于twitter输出。经过两个晚上的努力，初步实现了我想要的功能，并完成了前台页面的设计,IE下还是有点wacky :( 。Now this is the official release announcement: QQ签名秀web程序诞生! QQ签名秀网站 : http://punkid.org/qqsign/ 功能/Features 只需要简单的插入一行代码就能实现QQ签名的输出，而此过程的实现不需要你的主机支持php，也无须对XHTML有太多了解，一切我都替你完成了 支持UTF-8和GB18030两种编码输出 可定义显示最近QQ签名的条目数 发表时间显示为更人性化的&#8221;XX月XX天XX小时前&#8221; 可以通过CSS改变输出样式 可通过前台页面生成你需要的脚本代码，无须手动配置 前台页面配合预览功能，以验证输出的正确与完整 FAQ/疑问解答 为保证顺利抓取到你的&#8221;心路历程&#8221;xml文件，请确保你开启了QQ空间功能，并没有设置访问密码；与此同时，你还需要在Q-zone下设置把最新签名添加到&#8221;心路历程&#8221;下 UTF-8/GB18030该选择哪个编码呢? 国内很多网站都还在使用GB(GB2312,GBK,GB18030)码，而时下的趋势是使用UTF-8码，用什么编码取决于你的页面编码。例如blogbus用的就是UTF-8码。 显示条目数究竟能设置多大值? 因为QQ的xml文件并没有一次性输出所有历史签名，所以条目数不宜设置过大。当然，即使你设置值已经超过了最大实际值也不要紧，程序最自动输出到最大实际值后停止的 程序实现过程 这个程序的原理很简单，读取Q-zone里的&#8221;心路历程&#8221;的XML文件，经过数据处理后再输出为javascript形式。写这个程序遇到了四个困难: Q-zone的代码实在太乱太dirty了，腾讯又没有官方明确申明有RSS，而Q-zone又没法在非IE浏览器下浏览，我没办法使用FF下的firebug来inspect它的XML文件，最后通过从IE临时文件中找到js文件，把xml文件地址给揪了出来 我本打算采用php的SimpleXML/DomDocument直接读取QQ的XML文件，但是DH主机不支持URL-file-access mode，不得不放弃了这种最简单的方法，好在我曾经在给自己的blog写个wordpress插件时发现可以用MagpieRSS来读取XML文件，并最终通过MagpieRSS实现了成功读取 第三个困难是编码问题，QQ的xml输出的编码是GB2312，在我用MagpieRSS之前我曾考虑过用curl下载XML文件并储存为字符型数据，结果curl把GB码的汉字全丢掉了，更糟糕的是，我测试用的几个朋友的QQ签名里因为各式各样的非汉字/非英文特殊文字弄得读取出错，换成MagpieRSS后，发现指定输出编码的话也会出这样的问题，最终的办法是使用早先的MagpieRSS版本，不指定输出编码，直接读取XML数据储存为数组 最后一个问题是怎么把php执行的结果由javascript方式输出，研究了下livid的project babel程序ing模块代码，通过直接在php里写入javascript的document.write格式输出搞定了。 最后，特别感谢Druggo和我熬夜奋斗啊，很多东西都是他帮忙想辙的! And dont forget to send some feedbacks to me if you have some better ideas or suggestion.]]></description>
			<content:encoded><![CDATA[<p><img src="http://photo11.yupoo.com/20071020/235442_1179828962_naeqncuk.jpg" alt="qqsign" width="215" height="415" border="0" class="floatleft" /> 在上篇日志里我就提到要写一个输出QQ签名的程序了，作用是仅仅通过插入一行类似于豆瓣秀的代码在任意页面上显示最新的QQ签名，有点类似于twitter输出。经过两个晚上的努力，初步实现了我想要的功能，并完成了前台页面的设计,IE下还是有点wacky :( 。Now this is the official release announcement: QQ签名秀web程序诞生!</p>
<p><strong>QQ签名秀网站</strong> : <a href="http://punkid.org/qqsign/" title="Get QQ Signatures Show Now!">http://punkid.org/qqsign/</a></p>
<p><strong>功能/Features</strong></p>
<ul>
<li>只需要简单的插入一行代码就能实现QQ签名的输出，而此过程的实现不需要你的主机支持php，也无须对XHTML有太多了解，一切我都替你完成了</li>
<li>支持UTF-8和GB18030两种编码输出</li>
<li>可定义显示最近QQ签名的条目数</li>
<li>发表时间显示为更人性化的&#8221;XX月XX天XX小时前&#8221;</li>
<li>可以通过CSS改变输出样式</li>
<li>可通过前台页面生成你需要的脚本代码，无须手动配置</li>
<li>前台页面配合预览功能，以验证输出的正确与完整</li>
</ul>
<p><strong>FAQ/疑问解答</strong></p>
<ul>
<li>为保证顺利抓取到你的&#8221;心路历程&#8221;xml文件，请确保你开启了QQ空间功能，并没有设置访问密码；与此同时，你还需要在Q-zone下设置把最新签名添加到&#8221;心路历程&#8221;下</li>
<li>UTF-8/GB18030该选择哪个编码呢? 国内很多网站都还在使用GB(GB2312,GBK,GB18030)码，而时下的趋势是使用UTF-8码，用什么编码取决于你的页面编码。例如blogbus用的就是UTF-8码。</li>
<li>显示条目数究竟能设置多大值? 因为QQ的xml文件并没有一次性输出所有历史签名，所以条目数不宜设置过大。当然，即使你设置值已经超过了最大实际值也不要紧，程序最自动输出到最大实际值后停止的</li>
</ul>
<p><strong>程序实现过程</strong></p>
<p>这个程序的原理很简单，读取Q-zone里的&#8221;心路历程&#8221;的XML文件，经过数据处理后再输出为javascript形式。写这个程序遇到了四个困难:</p>
<ol>
<li>Q-zone的代码实在太乱太dirty了，腾讯又没有官方明确申明有RSS，而Q-zone又没法在非IE浏览器下浏览，我没办法使用FF下的firebug来inspect它的XML文件，最后通过从IE临时文件中找到js文件，把xml文件地址给揪了出来</li>
<li>我本打算采用php的SimpleXML/DomDocument直接读取QQ的XML文件，但是DH主机不支持URL-file-access mode，不得不放弃了这种最简单的方法，好在我曾经在给自己的blog写个wordpress插件时发现可以用<a href="http://magpierss.sourceforge.net/" title="MagpieRSS">MagpieRSS</a>来读取XML文件，并最终通过MagpieRSS实现了成功读取</li>
<li>第三个困难是编码问题，QQ的xml输出的编码是GB2312，在我用MagpieRSS之前我曾考虑过用curl下载XML文件并储存为字符型数据，结果curl把GB码的汉字全丢掉了，更糟糕的是，我测试用的几个朋友的QQ签名里因为各式各样的非汉字/非英文特殊文字弄得读取出错，换成MagpieRSS后，发现指定输出编码的话也会出这样的问题，最终的办法是使用早先的MagpieRSS版本，不指定输出编码，直接读取XML数据储存为数组</li>
<li>最后一个问题是怎么把php执行的结果由javascript方式输出，研究了下<a href="http://livid.cn" title="Livid Paranoid">livid</a>的project babel程序ing模块代码，通过直接在php里写入javascript的<code>document.write</code>格式输出搞定了。</li>
</ol>
<p>最后，特别感谢<a href="http://blog.druggo.net" title="Druggo">Druggo</a>和我熬夜奋斗啊，很多东西都是他帮忙想辙的! And dont forget to send some feedbacks to me if you have some better ideas or suggestion.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.punkid.org/2007/10/21/show-your-qq-signatures-in-blog/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>决定启用jQuery</title>
		<link>http://blog.punkid.org/2007/10/12/powered-with-jquery/</link>
		<comments>http://blog.punkid.org/2007/10/12/powered-with-jquery/#comments</comments>
		<pubDate>Fri, 12 Oct 2007 05:43:39 +0000</pubDate>
		<dc:creator>iPUNKID</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://blog.punkid.org/2007/10/12/powered-with-jquery/</guid>
		<description><![CDATA[这两天都在看jQuery的doc，发现这是个十分容易上手并掌握的javascript framework。正如其slogan说的一样: Write Less, Do More，连我这种javascript beginner也能很快的写出漂亮好用的代码来。 jQuery的代码很human-readable，即便是没看doc，光看代码也能明白这是拿来干嘛的，怎么运行的，稍微看下官方的tutorials后就可以自己写东西了。 个人认为jQuery最好用的是selectors和chain mechanism。它的selectors支持CSS和XPath，对我来说自然就是更熟悉CSS了，而且更关键的是它支持CSS3强大的选择器定义，我几乎可以用$("some CSS selectors")来定位到我需要的任何页面元素，只要会写CSS，就能很好的使用它的selectors。 jQuery比Mootools的代码更好写更易读的原因在于它的chain机制，利用selectors定位后就可以立即使用.action来执行动作了。以下面这段代码为例: $("#commentform input").each(function(){ if($(this).val() != '') {$(this).next(".overlabel").css("text-indent","-9999px;")}; $(this).focus(function(){ $(this).next(".overlabel").css("text-indent","-9999px"); }).blur(function(){ if($(this).val() == ''){ $(this).next(".overlabel").css("text-indent","0"); } }); }); 例如这段代码$(this).next(".overlabel").css("text-indent","-9999px;")，定位element后就可以连续发生系列动作，先移到下一元素(class为.overlabel的，就是我要的label)，然后赋予CSS style。 而$(this).focus ( function() {...} ).blur ( function() {...} ) 直接通过chain机制实现对focus和blur Event的分别动作，只要作用的是同一个对象，就可以不断的.action下去。 唯一让我有点不习惯的是它对$('some CSS selectors')所定位的对象是否存在的判断，不能直接用if ($('some CSS selectors')来判断是否存在，因为它返回的是对象本身，必须通过$('some CSS selectors').length来判断长度(没有存在对象即返回0值)，从而判断是否存在。 jQuery调试起来也很方便，只要有firefox下的firebug，写代码前完全可以在firebug里的console先试验下。这里有个很好的关于在firebug下调试jQuery的screencast。 当然，在我决定往blog里加载jQuery前，显然我更多的要考虑jQuery对加载速度的影响，几个jQuery的js文件加起来100多k，而我实际用到的可能不到20k，是否有必要加载一个这么大的东西来完成小部分工作? 最后我的办法是先把几个js文件合并为一个，用YUICompressor压缩，再启用gzip压缩，100多k的js最后大小仅为17k，从firebug里的加载速度来看，大概在700ms左右，有cache的话二次加载时间在400ms左右，这是比较可以接受的了。 目前的话并没有往blog里添加很多效果，我不喜欢添加乱七八糟的花哨特效&#8230;只是做了些小的应用，以及考虑到以后可能还要继续添加一些script进来。 P.S [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://photo5.yupoo.com/20071012/122031_694751185_fnjoeqvs.jpg" alt="jquery" width="500" height="110" border="0" /></p>
<p>这两天都在看<a href="http://jquery.com/" title="jQuery">jQuery</a>的doc，发现这是个十分容易上手并掌握的javascript framework。正如其slogan说的一样: <em>Write Less, Do More</em>，连我这种javascript beginner也能很快的写出漂亮好用的代码来。</p>
<p>jQuery的代码很human-readable，即便是没看doc，光看代码也能明白这是拿来干嘛的，怎么运行的，稍微看下官方的<a href="http://docs.jquery.com/How_jQuery_Works" title="Tutorials:How jQuery Works">tutorials</a>后就可以自己写东西了。<br />
<span id="more-151"></span><br />
个人认为jQuery最好用的是<em>selectors</em>和<em>chain</em> mechanism。它的<em>selectors</em>支持CSS和XPath，对我来说自然就是更熟悉CSS了，而且更关键的是它支持CSS3强大的选择器定义，我几乎可以用<code>$("some CSS selectors")</code>来定位到我需要的任何页面元素，只要会写CSS，就能很好的使用它的<em>selectors</em>。</p>
<p>jQuery比Mootools的代码更好写更易读的原因在于它的<em>chain</em>机制，利用<em>selectors</em>定位后就可以立即使用<code>.action</code>来执行动作了。以下面这段代码为例:</p>
<pre>
$("#commentform input").each(function(){
	if($(this).val() != '') {$(this).next(".overlabel").css("text-indent","-9999px;")};
	$(this).focus(function(){
		$(this).next(".overlabel").css("text-indent","-9999px");
	}).blur(function(){
	if($(this).val() == ''){
		$(this).next(".overlabel").css("text-indent","0");
	}
	});

});
</pre>
<p>例如这段代码<code>$(this).next(".overlabel").css("text-indent","-9999px;")</code>，定位element后就可以连续发生系列动作，先移到下一元素(class为<code>.overlabel</code>的，就是我要的<code>label</code>)，然后赋予CSS style。</p>
<p>而<code>$(this).focus ( function() {...} ).blur ( function() {...} )</code> 直接通过<em>chain</em>机制实现对<code>focus</code>和<code>blur</code> Event的分别动作，只要作用的是同一个对象，就可以不断的<code>.action</code>下去。</p>
<p>唯一让我有点不习惯的是它对<code>$('some CSS selectors')</code>所定位的对象是否存在的判断，不能直接用<code>if ($('some CSS selectors')</code>来判断是否存在，因为它返回的是对象本身，必须通过<code>$('some CSS selectors').length</code>来判断长度(没有存在对象即返回0值)，从而判断是否存在。</p>
<p>jQuery调试起来也很方便，只要有firefox下的<a href="http://getfirebug.com/" title="Get Firebug">firebug</a>，写代码前完全可以在firebug里的console先试验下。<a href="http://ejohn.org/blog/hacking-digg-with-firebug-and-jquery/" title="Hacking Digg With Firebug and jQuery">这里</a>有个很好的关于在firebug下调试jQuery的screencast。</p>
<p>当然，在我决定往blog里加载jQuery前，显然我更多的要考虑jQuery对加载速度的影响，几个jQuery的js文件加起来100多k，而我实际用到的可能不到20k，是否有必要加载一个这么大的东西来完成小部分工作? 最后我的办法是先把几个js文件合并为一个，用<a href="http://developer.yahoo.com/yui/compressor/" title="YUICompressor">YUICompressor</a>压缩，再启用gzip压缩，100多k的js最后大小仅为17k，从firebug里的加载速度来看，大概在700ms左右，有cache的话二次加载时间在400ms左右，这是比较可以接受的了。</p>
<p>目前的话并没有往blog里添加很多效果，我不喜欢添加乱七八糟的花哨特效&#8230;只是做了些小的应用，以及考虑到以后可能还要继续添加一些script进来。</p>
<p>P.S : 现在正开始逐步学习使用git做版本控制，拿vim写代码&#8230;以至于老是习惯性的在kwrite里编辑文字一停下来就按Esc键。更搞的是那天去食堂买水煮，老板问我要什么，我说&#8221;Ctrl+A，然后不要XX，不要XX&#8230;&#8221; Orz</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.punkid.org/2007/10/12/powered-with-jquery/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>让Feedburner的计数器重新显示</title>
		<link>http://blog.punkid.org/2007/10/05/bring-back-feedburner-counts-image-to-earth-in-china/</link>
		<comments>http://blog.punkid.org/2007/10/05/bring-back-feedburner-counts-image-to-earth-in-china/#comments</comments>
		<pubDate>Thu, 04 Oct 2007 19:05:50 +0000</pubDate>
		<dc:creator>iPUNKID</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[feedburner]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[计数器]]></category>

		<guid isPermaLink="false">http://blog.punkid.org/2007/10/05/bring-back-feedburner-counts-image-to-earth-in-china/</guid>
		<description><![CDATA[自从feedburner被河蟹之后，内地用户就没法看到那个fancy的feedburner计数器了，不过&#8230;Look at my site, I&#8217;ve brought it to earth! 原理很简单，利用国外的远程主机先在远程主机上获取feedburner的计数图片并保存在远程主机上，然后相应的修改feedburner的图片地址为保存在主机上的就行了。 我利用的是php方式来实现获取图片功能，代码如下 (其实我还是个php beginner，获取文件的代码是google来的) &#60;?php function get_feedburner&#40;&#36;url&#41; { //Initiate the curl // &#36;ch = curl_init&#40;&#41;; //Set the curl option// curl_setopt &#40;&#36;ch, CURLOPT_URL, &#36;url&#41;; curl_setopt &#40;&#36;ch, CURLOPT_HEADER, 0&#41;; ob_start&#40;&#41;; //Lets get the file// curl_exec &#40;&#36;ch&#41;; curl_close &#40;&#36;ch&#41;; //Retrieve the file got from the remote url// &#36;string = [...]]]></description>
			<content:encoded><![CDATA[<p>自从feedburner被河蟹之后，内地用户就没法看到那个fancy的feedburner计数器了，不过&#8230;Look at my site, I&#8217;ve brought it to earth! 原理很简单，利用国外的远程主机先在远程主机上获取feedburner的计数图片并保存在远程主机上，然后相应的修改feedburner的图片地址为保存在主机上的就行了。</p>
<p>我利用的是php方式来实现获取图片功能，代码如下 (其实我还是个php beginner，获取文件的代码是google来的)<br />
<span id="more-144"></span></p>
<pre>
&lt;?php
function get_feedburner&#40;&#36;url&#41; {

        //Initiate the curl //
	&#36;ch = curl_init&#40;&#41;;

	//Set the curl option//
	curl_setopt &#40;&#36;ch, CURLOPT_URL, &#36;url&#41;;
	curl_setopt &#40;&#36;ch, CURLOPT_HEADER, 0&#41;;

	ob_start&#40;&#41;;

        //Lets get the file//
	curl_exec &#40;&#36;ch&#41;;
	curl_close &#40;&#36;ch&#41;;

        //Retrieve the file got from the remote url//
	&#36;string = ob_get_contents&#40;&#41;;
	ob_end_clean&#40;&#41;;
	return &#36;string;
}

&#36;content = get_feedburner&#40;"http://feeds.feedburner.com/~fc/punkid?bg=BCF16C&amp;fg=404040&amp;anim=0"&#41;;
&#36;fp=fopen&#40;"feedburner.jpg", "w"&#41;;
fwrite&#40;&#36;fp, &#36;content&#41;;
fclose&#40;&#36;fp&#41;;
?&gt;
</pre>
<p>保存代码到<code>get_feedburner.php</code>文件中，其中<code>get_feedburner&#40&#41;</code>中的地址是你的feedburner计数器图片地址，而<code>fopen&#40&#41;</code>里是你将要保存到远程主机的图片名。想知道这个script到底有用不? ssh到远程主机执行<code>php get_feedburner.php</code>，然后用浏览器查看下保存的图片地址就知道了。</p>
<p>然后我们要做的是让这个script每天执行一次 (feedburner每天更新一次计数器数据)，ssh到远程主机运行<code>crontab -e</code>，添加如下一行:</p>
<pre>
01 9 * * * /usr/local/bin/php home/path/get_feedburner.php #请替换为你的<code>get_feedburner.php</code>保存地址。
</pre>
<p>这个cron job指示远程主机在每天9点01分时运行一次该script。为什么是9点捏? 我用的DH主机和我们这时差15个小时!</p>
<p>最后你要做的就是更改feedburner的计数器图片地址为你的主机上的图片地址吧。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.punkid.org/2007/10/05/bring-back-feedburner-counts-image-to-earth-in-china/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>The Art and Science of C  阅读笔记 II</title>
		<link>http://blog.punkid.org/2007/07/19/the-art-and-science-of-c-note-two/</link>
		<comments>http://blog.punkid.org/2007/07/19/the-art-and-science-of-c-note-two/#comments</comments>
		<pubDate>Thu, 19 Jul 2007 03:16:21 +0000</pubDate>
		<dc:creator>iPUNKID</dc:creator>
				<category><![CDATA[Mathematics]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[Taylor-Series]]></category>

		<guid isPermaLink="false">http://blog.punkid.org/2007/07/19/the-art-and-science-of-c-%e9%98%85%e8%af%bb%e7%ac%94%e8%ae%b0-ii/</guid>
		<description><![CDATA[对数学(尤其是大学高等数学)有恐惧心理的请略过吧&#8230; Algorithms (算法) 这一章有个运用泰勒公式(Taylor Series)求平方根(square root)的程序。虽然C语言的math.h库里已经有个sqrt的function了，不过这个sqrt function本身怎么写呢? 大学微积分里的泰勒公式终于派上用途了&#8230;我正好忘的一干二净了:) 先来学习/温习下泰勒公式吧: 后面的Rn(x) 是拉格朗日余项，当&#124;x-x0&#124;无穷小时，可以去掉拉格朗日余项，近似认为f(x) 等于前面的n项之和。 要求的是f(x) = &#8730;x，根据求导公式f'(X) = c Xc-1，得出f'(x0) = 1/2 x-1/2，二阶，三阶&#8230;N阶导以此类推。假设x0 = 1，则f(1) = 1, f'(1) = 1/2, f''(1) = - 1/4, f'''(1) = 3/8 ...。 将每项进行分拆，基本可以分为3个部分 xpower coeff ------------ factorical 其中的coeff是导数项fi(x0=1)，xpower是(x-1)i，factorical是阶乘项(i+1)! (i = 0,1,2&#8230;) 推到可知: coeff *= (0.5 - i); xpower *= (x - [...]]]></description>
			<content:encoded><![CDATA[<p><strong>对数学(尤其是大学高等数学)有恐惧心理的请略过吧&#8230;</strong></p>
<p><em>Algorithms</em> (算法) 这一章有个运用泰勒公式(Taylor Series)求平方根(square root)的程序。虽然C语言的<code>math.h</code>库里已经有个<code>sqrt</code>的function了，不过这个<code>sqrt</code> function本身怎么写呢? 大学微积分里的泰勒公式终于派上用途了&#8230;我正好忘的一干二净了:)</p>
<p>先来学习/温习下泰勒公式吧:<br />
<img src="http://photo6.yupoo.com/20070719/095546_1232394934_uyvmrfsw.jpg" alt="taylor series" width="500" height="36" border="0" /></p>
<p>后面的<code class="math">R<sub>n</sub>(x)</code> 是拉格朗日余项，当|x-x<sub>0</sub>|无穷小时，可以去掉拉格朗日余项，近似认为<code class="math">f(x)</code> 等于前面的n项之和。</p>
<p>要求的是<code class="math">f(x) = &radic;x</code>，根据求导公式<code class="math">f'(X) = c X<sup>c-1</sup></code>，得出<code class="math">f'(x<sub>0</sub>) = <sup>1</sup>/<sub>2</sub> x<sup>-<sup>1</sup>/<sub>2</sub></sup></code>，二阶，三阶&#8230;N阶导以此类推。假设x<sub>0</sub> = 1，则<code class="math">f(1) = 1, f'(1) = <sup>1</sup>/<sub>2</sub>, f''(1) = - <sup>1</sup>/<sub>4</sub>, f'''(1) = <sup>3</sup>/<sub>8</sub> ...</code>。<br />
<span id="more-98"></span><br />
将每项进行分拆，基本可以分为3个部分</p>
<pre>
         xpower
coeff ------------
       factorical
</pre>
<p>其中的<code>coeff</code>是导数项<code class="math">f<sup>i</sup>(x<sub>0</sub>=1)</code>，<code>xpower</code>是<code class="math">(x-1)<sup>i</sup></code>，<code>factorical</code>是阶乘项<code class="math">(i+1)!</code> (i = 0,1,2&#8230;)</p>
<p>推到可知:</p>
<pre>
coeff *= (0.5 - i);
xpower *= (x - 1);
factorial *= (i + 1);
</pre>
<p>所以用泰勒公式求平方根就可以可以编写C程序了</p>
<pre>
double TSqrt(double x)
{
     double sum, factorial, coeff, term, xpower;
     int i;

     factorial = coeff = xpower = 1;
     sum = 0;
     term = 1;
     for (i=0; sum != sum + term; i++) {
          sum += term;
          coeff *= (0.5 - i);
          xpower *= (x -1);
          factorial *= (i + 1);
          term = coeff * xpower / factorial;
     }
     return (sum);
}
</pre>
<p>泰勒公式自然是要求i值越大，结果越精确，但是这就陷入了C语言中的无限循环，程序永远不会停止也得不到结果。为了限定<code>for</code>循环的运算次数，可以设定条件为<code>sum != sum + term</code>，<code>即当sum = sum + term</code>时跳出循环。因为<code>sum</code>和<code>term</code>都是<code>double</code>型，其值是不精确的，所以随着循环次数的不断进行，后面的项数值<code>term</code>会越来越趋近于无穷小，例如当sum = 23，而term = 0.000000000001时，计算机会认为 23 (sum) = 23.000000000001 (sum + term)。</p>
<p>不过这个程序还有个问题，就是当假设x<sub>0</sub> = 1时，泰勒公式要求x的取值范围是:</p>
<pre>0 < x <2</pre>
<p>否则随着x的增大，运算结果会越来越失真。</p>
<p>解决办法的思路是: 因为 <code class="math">&radic;4x = &radic;4 &radic;x = 2&radic;x</code>，我们可以把大数通过不断的除4最终化为(0,2)区间的小数。只要记得除了多少次4，最后在结果上乘上这个次数的2就行了。</p>
<pre>
double Sqrt(double x)
{
    double correction;
    if (x == 0) return (0);
    if (x < 0) Error("Sqrt called with negative argument %g", x);
    correction = 1;
    while (x >=2) {
         x /= 4;
         correction *= 2;
    }
    return (TSqrt(x) * correction);
}
</pre>
<p>特别要注意的是，x是<code>double</code>型，才能保证除以4后的数为带小数位的较精确值，而不是去尾的整数。想象如果x是<code>int</code>型，那么16和17的运算结果会是一样的。</p>
<p>OK，整个运用泰勒公式求平方根的程序就出来了:</p>
<pre>
/*
 * Function : Sqrt
 * Usage: root = Sqrt(x);
 * -------------------------------
 * Description: Returns the square root of x.
 * /

double Sqrt(double x)
{
    double correction;
    if (x == 0) return (0);
    if (x < 0) Error("Sqrt called with negative argument %g", x);
    correction = 1;
    while (x >=2) {
         x /= 4;
         correction *= 2;
    }
    return (TSqrt(x) * correction);
}

/*
 * Function : TSqrt
 * Usage: root = TSqrt(x);
 * ---------------------------------
 * Description: Returns the square root of x in the range 0 &lt; x &lt; 2.
 * /

double TSqrt(double x)
{
     double sum, factorial, coeff, term, xpower;
     int i;

     factorial = coeff = xpower = 1;
     sum = 0;
     term = 1;
     for (i=0; sum != sum + term; i++) {
          sum += term;
          coeff *= (0.5 - i);
          xpower *= (x -1);
          factorial *= (i + 1);
          term = coeff * xpower / factorial;
     }
     return (sum);
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.punkid.org/2007/07/19/the-art-and-science-of-c-note-two/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>The Art and Science of C 阅读笔记 I</title>
		<link>http://blog.punkid.org/2007/07/15/the-art-and-science-of-c-note-one/</link>
		<comments>http://blog.punkid.org/2007/07/15/the-art-and-science-of-c-note-one/#comments</comments>
		<pubDate>Sun, 15 Jul 2007 15:56:59 +0000</pubDate>
		<dc:creator>iPUNKID</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[The-Art-and-Science-of-C]]></category>

		<guid isPermaLink="false">http://blog.punkid.org/2007/07/15/the-art-and-science-of-c-note-one/</guid>
		<description><![CDATA[The Art and Science of C (C语言的科学与艺术) 已经读完4章了，这确实是本非常不错的Programming类书籍，我喜欢它循序渐进的讲述方法，讲问题不拖泥带水也绝不含糊，不像国内那位谭某人写的传说中的经典版C语言教材，废话一大堆还没讲明白个所以然，而且那是相当的过时啊，要知道这本The Art and Science of C 还是94年出版的。总而言之，我们在用本世纪的国内垃圾教材学习早在上世纪90年代前期就已过时的知识。废话完毕，正式开始笔记: 1. 一定要记得在main程序段前加入需要的库，最基本的两个就是: #include &#60;stdio.h&#62; #include "genlib.h" main() { ... } 习惯在Win下用Turbo C编写C程序的人最容易忽视这两个库文件了，因为Turbo C是默认就为程序引用这两个库的。如果你在linux下用gcc编译C程序的话，没有加入库文件它会有警告提示的。 2. linux下编译C程序的方法是，gcc -o hello.out hello.c，编译hello.c的程序并生成hellp.out的执行程序，如不使用-o hello.out参数指定输出执行程序的名字的话，会默认输出名为a.out的执行程序。使用./ hello.out来进行函数赋值输入 3. 还在使用scanf进行输入操作？这个方法在94年就不提倡了。对于int型，可以使用var = GetInteger来输入赋值，double型可以使用var = GetReal(), string型则是var = GetLine()。 printf("Please assign a value for n"); /*你可以用scanf来搞定*/ scanf("%d",&#038;n); /*现在你可以用GetInteger操作，它看起来更符合现代程序的书写习惯*/ n=GetInteger(); 4. 两个int值运算结果还是int，只要有一个是double，无论另一个是int还是double其运算结果都是double。当然指定了数值类型那就不一样了，看以下实例分析: [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.douban.com/subject/1148265/" title="The Art and Science of C:A Library-Based Introduction to Computer Science">The Art and Science of C</a> (C语言的科学与艺术) 已经读完4章了，这确实是本非常不错的Programming类书籍，我喜欢它循序渐进的讲述方法，讲问题不拖泥带水也绝不含糊，不像国内那位谭某人写的传说中的经典版C语言教材，废话一大堆还没讲明白个所以然，而且那是相当的过时啊，要知道这本<em>The Art and Science of C</em> 还是94年出版的。总而言之，我们在用本世纪的国内垃圾教材学习早在上世纪90年代前期就已过时的知识。废话完毕，正式开始笔记:</p>
<p>1. 一定要记得在<code>main</code>程序段前加入需要的库，最基本的两个就是:</p>
<pre>
#include &lt;stdio.h&gt;
#include "genlib.h"

main() {
    ...
}
</pre>
<p>习惯在Win下用Turbo C编写C程序的人最容易忽视这两个库文件了，因为Turbo C是默认就为程序引用这两个库的。如果你在linux下用gcc编译C程序的话，没有加入库文件它会有警告提示的。</p>
<p>2. linux下编译C程序的方法是，<code>gcc -o hello.out hello.c</code>，编译hello.c的程序并生成hellp.out的执行程序，如不使用<code>-o hello.out</code>参数指定输出执行程序的名字的话，会默认输出名为a.out的执行程序。使用<code>./ hello.out</code>来进行函数赋值输入<br />
<span id="more-96"></span><br />
3. <del datetime="2007-10-15T05:08:07+00:00">还在使用<code>scanf</code>进行输入操作？这个方法在94年就不提倡了。</del>对于<code>int</code>型，可以使用<code>var = GetInteger</code>来输入赋值，<code>double</code>型可以使用<code>var = GetReal()</code>, <code>string</code>型则是<code>var = GetLine()</code>。</p>
<pre>
printf("Please assign a value for n");
/*你可以用<code>scanf</code>来搞定*/
scanf("%d",&#038;n);

/*现在你可以用<code>GetInteger</code>操作，<del datetime="2007-10-15T05:08:07+00:00">它看起来更符合现代程序的书写习惯</del>*/
n=GetInteger();
</pre>
<p>4. 两个<code>int</code>值运算结果还是<code>int</code>，只要有一个是<code>double</code>，无论另一个是<code>int</code>还是<code>double</code>其运算结果都是<code>double</code>。当然指定了数值类型那就不一样了，看以下实例分析:</p>
<pre>
/*两个<code>int</code>型相加其结果还是<code>int</code>型*/
1 + 1 = 2 

/*有一个是<code>double</code>型其结果就是<code>double</code>了*/
1.0 + 1 = 2.0 

/*通过在数值前使用<code>(int)</code>来指定数值类型会自动去尾(truncated)将其转换为<code>int</code>型。*/
(int)1.0 + 1 = 2 

/*=号运算是从右到左，<code>d = i = 1.5</code>相当与<code>d = (i = 1.5)</code>，因为i是<code>int</code>型，所以i 的值为1，但又因为d是<code>double</code>型，所以d的值是1.0。*/
double d; int i;
d = i = 1.5;
</pre>
<p>5. <code>printf("%-10d",n)</code> 的意思不是显示时给n赋予负值，而是通过给定的10位宽度，- 号表示在这10位宽度里从左对齐(left-aligned)显示，这个- 号在table布局显示数据时很有用。</p>
<p>6. <code>main() {}</code> 其实就是个程序(function)，每个function都是由<code>function() {content}</code> 结构组成的而已。</p>
<p>7. 养成良好的代码书写习惯和风格，<strong>Good style and program readability are critical for program maintenance</strong>。例如:</p>
<pre>
/*
 *  File : hello.c
 *  ----------------
 *  Description : To display hello text and show what a basic C program is
 */

#include &lt;stdio.h&gt;
#include "genlib.h"
#include "simpio.h"

/* Main program */

main() {
    int i;

    printf("Please assign a value for i");
    i = GetInteger();
    printf("I = %d",i);
}
</pre>
<p>给于程序适当的解释说明信息，以及注意程序块的缩进(indentation)以提高可读性。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.punkid.org/2007/07/15/the-art-and-science-of-c-note-one/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

