<?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; Algorithms</title>
	<atom:link href="http://blog.punkid.org/tag/algorithms/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>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>
	</channel>
</rss>

