mirror of
https://github.com/gopl-zh/gopl-zh.github.com.git
synced 2026-01-15 11:47:14 +08:00
rebuild
This commit is contained in:
@@ -21,6 +21,10 @@
|
||||
<link rel="stylesheet" href="../gitbook/style.css">
|
||||
|
||||
|
||||
<link rel="stylesheet" href="../gitbook/plugins/gitbook-plugin-katex/katex.min.css">
|
||||
|
||||
|
||||
|
||||
<link rel="stylesheet" href="../gitbook/plugins/gitbook-plugin-highlight/website.css">
|
||||
|
||||
|
||||
@@ -44,7 +48,7 @@
|
||||
<body>
|
||||
|
||||
|
||||
<div class="book" data-level="3.2" data-chapter-title="浮點數" data-filepath="ch3/ch3-02.md" data-basepath=".." data-revision="Fri Dec 25 2015 12:32:44 GMT+0800 (中国标准时间)">
|
||||
<div class="book" data-level="3.2" data-chapter-title="浮點數" data-filepath="ch3/ch3-02.md" data-basepath=".." data-revision="Mon Dec 28 2015 16:03:52 GMT+0800 (中国标准时间)">
|
||||
|
||||
|
||||
<div class="book-summary">
|
||||
@@ -238,7 +242,7 @@
|
||||
|
||||
<b>1.5.</b>
|
||||
|
||||
穫取URL
|
||||
獲取URL
|
||||
</a>
|
||||
|
||||
|
||||
@@ -253,7 +257,7 @@
|
||||
|
||||
<b>1.6.</b>
|
||||
|
||||
併發穫取多個URL
|
||||
併發獲取多個URL
|
||||
</a>
|
||||
|
||||
|
||||
@@ -802,7 +806,7 @@
|
||||
|
||||
<b>5.10.</b>
|
||||
|
||||
Recover捕穫異常
|
||||
Recover捕獲異常
|
||||
</a>
|
||||
|
||||
|
||||
@@ -1315,7 +1319,7 @@
|
||||
|
||||
<b>8.9.</b>
|
||||
|
||||
併發的退齣
|
||||
併發的退出
|
||||
</a>
|
||||
|
||||
|
||||
@@ -1834,7 +1838,7 @@
|
||||
|
||||
<b>12.7.</b>
|
||||
|
||||
穫取結構體字段標識
|
||||
獲取結構體字段標識
|
||||
</a>
|
||||
|
||||
|
||||
@@ -2020,25 +2024,25 @@
|
||||
<section class="normal" id="section-">
|
||||
|
||||
<h2 id="32-浮點數">3.2. 浮點數</h2>
|
||||
<p>Go語言提供了兩種精度的浮點數, float32 和 float64. 它們的算術規范由 IEEE754 國際標準定義, 該浮點數規范被所有現代的CPU支持.</p>
|
||||
<p>這些數值類型的范圍可以從很微小到很鉅大. 浮點數的范圍極限值可以在 matn 包找到. 常量 math.MaxFloat32 表示 float32 能表示的最大數值, 大約是 3.4e38, 對應的 math.MaxFloat64 常量大約是 1.8e308. 它們能表示的最小值近似分别是1.4e-45 和 4.9e-324.</p>
|
||||
<p>一個 float32 類型的浮點數可以提供大約6個十進製數的精度, 而 float64 則可以提供約 15個十進製數精度; 通常應該優先使用 float64 類型, 因爲 float32 類型的纍計計算誤差很容易擴散, 併且 float32 能精度表示的正整數併不是很大:</p>
|
||||
<p>Go語言提供了兩種精度的浮點數,float32和float64。它們的算術規范由IEEE754浮點數国際標準定義,該浮點數規范被所有現代的CPU支持。</p>
|
||||
<p>這些浮點數類型的取值范圍可以從很微小到很鉅大。浮點數的范圍極限值可以在math包找到。常量math.MaxFloat32表示float32能表示的最大數值,大約是 3.4e38;對應的math.MaxFloat64常量大約是1.8e308。它們分别能表示的最小值近似爲1.4e-45和4.9e-324。</p>
|
||||
<p>一個float32類型的浮點數可以提供大約6個十進製數的精度,而float64則可以提供約15個十進製數的精度;通常應該優先使用float64類型,因爲float32類型的纍計計算誤差很容易擴散,併且float32能精確表示的正整數併不是很大(譯註:因爲float32的有效bit位隻有23個,其它的bit位用於指數和符號;當整數大於23bit能表達的范圍時,float32的表示將出現誤差):</p>
|
||||
<pre><code class="lang-Go"><span class="hljs-keyword">var</span> f <span class="hljs-typename">float32</span> = <span class="hljs-number">16777216</span> <span class="hljs-comment">// 1 << 24</span>
|
||||
fmt.Println(f == f+<span class="hljs-number">1</span>) <span class="hljs-comment">// "true"!</span>
|
||||
</code></pre>
|
||||
<p>浮點數的字面值可以直接寫小數部分, 想這樣:</p>
|
||||
<p>浮點數的字面值可以直接寫小數部分,像這樣:</p>
|
||||
<pre><code class="lang-Go"><span class="hljs-keyword">const</span> e = <span class="hljs-number">2.71828</span> <span class="hljs-comment">// (approximately)</span>
|
||||
</code></pre>
|
||||
<p>小數點前面或後面的數字都可能被省略(例如 .707 或 1.). 很小或很大的數最好用科學計數法書寫, 通過e或E來指定指數部分:</p>
|
||||
<pre><code class="lang-Go"><span class="hljs-keyword">const</span> Avogadro = <span class="hljs-number">6.02214129e23</span>
|
||||
<span class="hljs-keyword">const</span> Planck = <span class="hljs-number">6.62606957e-34</span>
|
||||
<p>小數點前面或後面的數字都可能被省略(例如.707或1.)。很小或很大的數最好用科學計數法書寫,通過e或E來指定指數部分:</p>
|
||||
<pre><code class="lang-Go"><span class="hljs-keyword">const</span> Avogadro = <span class="hljs-number">6.02214129e23</span> <span class="hljs-comment">// 阿伏伽德羅常數</span>
|
||||
<span class="hljs-keyword">const</span> Planck = <span class="hljs-number">6.62606957e-34</span> <span class="hljs-comment">// 普朗剋常數</span>
|
||||
</code></pre>
|
||||
<p>用 Printf 函數的 %g 參數打印浮點數, 將采用緊湊的表示形式打印, 併提供足夠的精度, 但是對應表格的數據, 使用 %e (帶指數) 或 %f 的形式打印可能更合適. 所有的這三個打印形式都可以指定打印的寬度和控製打印精度.</p>
|
||||
<p>用Printf函數的%g參數打印浮點數,將采用更緊湊的表示形式打印,併提供足夠的精度,但是對應表格的數據,使用%e(帶指數)或%f的形式打印可能更合適。所有的這三個打印形式都可以指定打印的寬度和控製打印精度。</p>
|
||||
<pre><code class="lang-Go"><span class="hljs-keyword">for</span> x := <span class="hljs-number">0</span>; x < <span class="hljs-number">8</span>; x++ {
|
||||
fmt.Printf(<span class="hljs-string">"x = %d e^x = %8.3f\n"</span>, x, math.Exp(<span class="hljs-typename">float64</span>(x)))
|
||||
}
|
||||
</code></pre>
|
||||
<p>上面代碼打印e的冪, 打印精度是小數點後三個小數精度和8個字符寬度:</p>
|
||||
<p>上面代碼打印e的冪,打印精度是小數點後三個小數精度和8個字符寬度:</p>
|
||||
<pre><code>x = 0 e^x = 1.000
|
||||
x = 1 e^x = 2.718
|
||||
x = 2 e^x = 7.389
|
||||
@@ -2047,15 +2051,15 @@ x = 4 e^x = 54.598
|
||||
x = 5 e^x = 148.413
|
||||
x = 6 e^x = 403.429
|
||||
x = 7 e^x = 1096.633
|
||||
</code></pre><p>math 包中除了提供大量常用的數學函數外, 還提供了IEEE754標準中特殊數值的創建和測試: 正無窮大和負無窮大, 分别用於表示太大溢齣的數字和除零的結果; 還有 NaN 非數, 一般用於表示無效的除法操作結果 0/0 或 Sqrt(-1).</p>
|
||||
</code></pre><p>math包中除了提供大量常用的數學函數外,還提供了IEEE754浮點數標準中定義的特殊值的創建和測試:正無窮大和負無窮大,分别用於表示太大溢出的數字和除零的結果;還有NaN非數,一般用於表示無效的除法操作結果0/0或Sqrt(-1).</p>
|
||||
<pre><code class="lang-Go"><span class="hljs-keyword">var</span> z <span class="hljs-typename">float64</span>
|
||||
fmt.Println(z, -z, <span class="hljs-number">1</span>/z, -<span class="hljs-number">1</span>/z, z/z) <span class="hljs-comment">// "0 -0 +Inf -Inf NaN"</span>
|
||||
</code></pre>
|
||||
<p>函數 math.IsNaN 用於測試一個數是否是非數 NaN, math.NaN 則返迴非數對應的值. 雖然可以用 math.NaN 來表示一個非法的結果, 但是測試一個結果是否是非數 NaN 則是充滿風險, 因爲 NaN 和任何數都是不相等的:</p>
|
||||
<p>函數math.IsNaN用於測試一個數是否是非數NaN,math.NaN則返迴非數對應的值。雖然可以用math.NaN來表示一個非法的結果,但是測試一個結果是否是非數NaN則是充滿風險的,因爲NaN和任何數都是不相等的(譯註:在浮點數中,NaN、正無窮大和負無窮大都不是唯一的,每個都有非常多種的bit模式表示):</p>
|
||||
<pre><code class="lang-Go">nan := math.NaN()
|
||||
fmt.Println(nan == nan, nan < nan, nan > nan) <span class="hljs-comment">// "false false false"</span>
|
||||
</code></pre>
|
||||
<p>如果一個函數返迴的浮點數結果可能失敗, 最好的做法是用單獨的標誌報告失敗, 像這樣:</p>
|
||||
<p>如果一個函數返迴的浮點數結果可能失敗,最好的做法是用單獨的標誌報告失敗,像這樣:</p>
|
||||
<pre><code class="lang-Go"><span class="hljs-keyword">func</span> compute() (value <span class="hljs-typename">float64</span>, ok <span class="hljs-typename">bool</span>) {
|
||||
<span class="hljs-comment">// ...</span>
|
||||
<span class="hljs-keyword">if</span> failed {
|
||||
@@ -2064,7 +2068,7 @@ fmt.Println(nan == nan, nan < nan, nan > nan) <span class="hljs-comment">/
|
||||
<span class="hljs-keyword">return</span> result, <span class="hljs-constant">true</span>
|
||||
}
|
||||
</code></pre>
|
||||
<p>接下來的程序演示了浮點計算圖形. 它是帶有兩個參數的 z = f(x, y) 函數的三維形式, 使用了可縮放矢量圖形(SVG)格式輸齣, 一個用於矢量線繪製的XML標準. 圖3.1顯示了 sin(r)/r 函數的輸齣圖形, 其中 r 是 sqrt(x<em>x+y</em>y).</p>
|
||||
<p>接下來的程序演示了通過浮點計算生成的圖形。它是帶有兩個參數的z = f(x, y)函數的三維形式,使用了可縮放矢量圖形(SVG)格式輸出,SVG是一個用於矢量線繪製的XML標準。圖3.1顯示了sin(r)/r函數的輸出圖形,其中r是sqrt(x<em>x+y</em>y)。</p>
|
||||
<p><img src="../images/ch3-01.png" alt=""></p>
|
||||
<pre><code class="lang-Go">gopl.io/ch3/surface
|
||||
<span class="hljs-comment">// Surface computes an SVG rendering of a 3-D surface function.</span>
|
||||
@@ -2122,20 +2126,20 @@ fmt.Println(nan == nan, nan < nan, nan > nan) <span class="hljs-comment">/
|
||||
<span class="hljs-keyword">return</span> math.Sin(r) / r
|
||||
}
|
||||
</code></pre>
|
||||
<p>要註意的是 corner 返迴了兩個結果, 對應 corner 的坐標參數.</p>
|
||||
<p>要解釋程序是如何工作的需要了解基本的幾何知識, 但是我們可以跳過幾何原理, 因爲程序的重點是演示浮點運算. 程序的本質是三個不同的坐標繫中映射關繫, 如圖3.2所示. 第一個是 100x100 的二維網格, 對應整數整數坐標(i,j), 從遠處的 (0, 0) 位置開始. 我們從遠處像前面繪製, 因此遠處先繪製的多邊形有可能被前面後繪製的多邊形覆蓋.</p>
|
||||
<p>第二個坐標繫是一個三維的網格浮點坐標(x,y,z), 其中x和y是i和j的線性函數, 通過平移轉換位center的中心, 然後用xyrange繫數縮放. 高度z是函數f(x,y)的值.</p>
|
||||
<p>第三個坐標繫是一個二維的畵布, 起點(0,0)在左上角. 畵布中點的坐標用(sx, sy)表示. 我們使用等角投影將三維點</p>
|
||||
<p>要註意的是corner函數返迴了兩個結果,分别對應每個網格頂點的坐標參數。</p>
|
||||
<p>要解釋這個程序是如何工作的需要一些基本的幾何學知識,但是我們可以跳過幾何學原理,因爲程序的重點是演示浮點數運算。程序的本質是三個不同的坐標繫中映射關繫,如圖3.2所示。第一個是100x100的二維網格,對應整數整數坐標(i,j),從遠處的(0, 0)位置開始。我們從遠處向前面繪製,因此遠處先繪製的多邊形有可能被前面後繪製的多邊形覆蓋。</p>
|
||||
<p>第二個坐標繫是一個三維的網格浮點坐標(x,y,z),其中x和y是i和j的線性函數,通過平移轉換位網格單元的中心,然後用xyrange繫數縮放。高度z是函數f(x,y)的值。</p>
|
||||
<p>第三個坐標繫是一個二維的畵布,起點(0,0)在左上角。畵布中點的坐標用(sx, sy)表示。我們使用等角投影將三維點</p>
|
||||
<p><img src="../images/ch3-02.png" alt=""></p>
|
||||
<p>(x,y,z) 投影到二維的畵布中. 畵布中從遠處到右邊的點對應較大的x值和較大的y值. 併且畵布中x和y值越大, 則對應的z值越小. x和y的垂直和水平縮放繫數來自30度角的正絃和餘絃值. z的縮放繫數0.4, 是一個任意選擇的參數.</p>
|
||||
<p>對於二維網格中的每一個單位, main函數計算單元的四個頂點在畵布中對應多邊形ABCD的頂點, 其中B對應(i,j)頂點位置, A, C, 和 D是相鄰的頂點, 然後輸齣SVG的繪製指令.</p>
|
||||
<p><strong>練習3.1:</strong> 如果 f 函數返迴的是無限製的 float64 值, 那麽SVG文件可能輸齣無效的<polygon></polygon>多邊形元素(雖然許多SVG渲染器會妥善處理這類問題). 脩改程序跳過無效的多邊形.</p>
|
||||
<p><strong>練習3.2:</strong> 試驗math包中其他函數的渲染圖形. 你是否能輸齣一個egg box, moguls, 或 a saddle 圖案?</p>
|
||||
<p><strong>練習3.3:</strong>根據高度給每個多邊形上色, 那樣峯值部將是紅色(#ff0000), 谷部將是藍色(#0000ff).</p>
|
||||
<p><strong>3.4:</strong> 參考1.7節Lissajous例子的函數, 構造一個web服務器, 用於計算函數麴面然後返迴SVG數據給客戶端. 服務器必鬚設置 Content-Type 頭部:</p>
|
||||
<p>(x,y,z)投影到二維的畵布中。畵布中從遠處到右邊的點對應較大的x值和較大的y值。併且畵布中x和y值越大,則對應的z值越小。x和y的垂直和水平縮放繫數來自30度角的正絃和餘絃值。z的縮放繫數0.4,是一個任意選擇的參數。</p>
|
||||
<p>對於二維網格中的每一個網格單元,main函數計算單元的四個頂點在畵布中對應多邊形ABCD的頂點,其中B對應(i,j)頂點位置,A、C和D是其它相鄰的頂點,然後輸出SVG的繪製指令。</p>
|
||||
<p><strong>練習 3.1:</strong> 如果f函數返迴的是無限製的float64值,那麽SVG文件可能輸出無效的<polygon></polygon>多邊形元素(雖然許多SVG渲染器會妥善處理這類問題)。脩改程序跳過無效的多邊形。</p>
|
||||
<p><strong>練習 3.2:</strong> 試驗math包中其他函數的渲染圖形。你是否能輸出一個egg box、moguls或a saddle圖案?</p>
|
||||
<p><strong>練習 3.3:</strong> 根據高度給每個多邊形上色,那樣峯值部將是紅色(#ff0000),谷部將是藍色(#0000ff)。</p>
|
||||
<p><strong>練習 3.4:</strong> 參考1.7節Lissajous例子的函數,構造一個web服務器,用於計算函數麴面然後返迴SVG數據給客戶端。服務器必鬚設置Content-Type頭部:</p>
|
||||
<pre><code class="lang-Go">w.Header().Set(<span class="hljs-string">"Content-Type"</span>, <span class="hljs-string">"image/svg+xml"</span>)
|
||||
</code></pre>
|
||||
<p>(這一步在Lissajous例子中不是必鬚的, 因爲服務器使用標準的PNG圖像格式, 可以根據前面的512個字節自動輸齣對應的頭部.) 允許客戶端通過HTTP請求參數設置高度, 寬度, 和顔色等參數.</p>
|
||||
<p>(這一步在Lissajous例子中不是必鬚的,因爲服務器使用標準的PNG圖像格式,可以根據前面的512個字節自動輸出對應的頭部。)允許客戶端通過HTTP請求參數設置高度、寬度和顔色等參數。</p>
|
||||
|
||||
|
||||
</section>
|
||||
@@ -2167,7 +2171,7 @@ fmt.Println(nan == nan, nan < nan, nan > nan) <span class="hljs-comment">/
|
||||
|
||||
<script>
|
||||
require(["gitbook"], function(gitbook) {
|
||||
var config = {"highlight":{},"sharing":{"facebook":true,"twitter":true,"google":false,"weibo":false,"instapaper":false,"vk":false,"all":["facebook","google","twitter","weibo","instapaper"]},"fontsettings":{"theme":"white","family":"sans","size":2}};
|
||||
var config = {"katex":{},"highlight":{},"sharing":{"facebook":true,"twitter":true,"google":false,"weibo":false,"instapaper":false,"vk":false,"all":["facebook","google","twitter","weibo","instapaper"]},"fontsettings":{"theme":"white","family":"sans","size":2}};
|
||||
gitbook.start(config);
|
||||
});
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user