<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # **第 12 章 數值類** 到現在為止,數值(Numeric)類已經出現過好多次了。接下來我們就來詳細討論一下數值類的加減運算等基本操作、以及一些常用的功能。 - **數值類的構成** 介紹包含 `Fixnum`、`Float` 等在內的數值類的構成。 - **數值的字面量(literal)** 介紹在程序中描述數值的各種方法。 - **算術運算** 介紹四則運算等基本的算術運算、以及數值運算時使用的模塊 Math 的用法。 - **類型轉換** 介紹轉換數值類型的方法,例如 `Integer` 與 `Float` 的互相轉換。 - **位運算** 介紹進行位運算的運算符。 - **隨機數** 介紹獲取隨機數時使用的相關功能。 - **計數** 介紹通過 `Integer` 指定循環次數的方法。 ### **12.1 數值類的構成** 在數值類中,有像 -1、0、1、10 這樣的表示整數的 `Integer` 類,也有像 0.1、3.141592 這樣的具有精度的、表示浮點小數的 `Float` 類。 這些數值類都被定義為了 `Numeric` 類的子類。另外,`Integer` 類又可以分為兩種,一種是表示計算機硬件可以處理的數值的 `Fixnum` 類,另外一種是表示比 `Fixnum` 更大的數值的 `Bignum` 類。 ![{%}](https://box.kancloud.cn/2015-10-26_562e01efb6396.png) 程序中用到的整數一般都是 `Fixnum` 類范圍內的整數。如果使用的整數超過了 `Fixnum` 的范圍,Ruby 就會自動將其轉換為 `Bignum` 類。因此,在寫程序的時候,我們幾乎可以忽略上述整數類的區別。下面是計算 2 的 10 次冪以及 2 的 1000 次冪的例子,`**` 是表示乘方的運算符。 > **執行示例** ~~~ > irb --simple-prompt >> n = 2 ** 10 => 1024 >> n.class => Fixnum >> m = 2 ** 1000 => 1071508607186267320948425049060001810561404811705533607443750388370351051124936 1224931983788156958581275946729175531468251871452856923140435984577574698574803934 5677748242309854210746050623711418779541821530464749835819412673987675591655439460 77062914571196477686542167660429831652624386837205668069376 >> m.class => Bignum ~~~ Ruby 也可以處理有理數和復數。表示有理數用 `Rational` 類,表示復數用 `Complex` 類。 `Rational` 對象用“`Rational( 分子 , 分母 )`”的形式定義,例如, ![\frac{2}{5}+\frac{1}{3} ](http://latex.codecogs.com/gif.latex?/frac{2}{5}+/frac{1}{3}) 上述這樣的分數計算,可以用 `Rational` 對象改寫成下面那樣。我們還可以使用 `Rational#to_f` 方法將其轉換為 `Float` 對象。 ~~~ a = Rational(2, 5) b = Rational(1, 3) p a #=> (2/5) p b #=> (1/3) c = a + b p c #=> (11/15) p c.to_f #=> 0.7333333333333333 ~~~ `Complex` 對象用“`Complex( 實數 , 虛數 )`”的形式定義。以下是計算復數 2i 的 2 次冪的例子: ~~~ c = Complex(0, 2) ** 2 p c #=> (-4+0i) ~~~ ### **12.2 數值的字面量** 表 12.1 是表示數值對象的字面量的例子。 **表 12.1 數值對象的字面量** <table border="1" data-line-num="80 81 82 83 84 85 86 87 88 89 90 91" width="90%"><thead><tr><th> <p class="表頭單元格">字面量</p> </th> <th> <p class="表頭單元格">作用(括號內為 10 進制的值)</p> </th> </tr></thead><tbody><tr><td> <p class="表格單元格"><code>123</code></p> </td> <td> <p class="表格單元格">表示10 進制整數</p> </td> </tr><tr><td> <p class="表格單元格"><code>0123</code></p> </td> <td> <p class="表格單元格">表示8 進制整數(83)</p> </td> </tr><tr><td> <p class="表格單元格"><code>0o123</code></p> </td> <td> <p class="表格單元格">表示8 進制整數(83)</p> </td> </tr><tr><td> <p class="表格單元格"><code>0d123</code></p> </td> <td> <p class="表格單元格">表示10 進制整數(123)</p> </td> </tr><tr><td> <p class="表格單元格"><code>0x123</code></p> </td> <td> <p class="表格單元格">表示16 進制整數(291)</p> </td> </tr><tr><td> <p class="表格單元格"><code>0b1111011</code></p> </td> <td> <p class="表格單元格">表示2 進制整數(123)</p> </td> </tr><tr><td> <p class="表格單元格"><code>123.45</code></p> </td> <td> <p class="表格單元格">浮點小數</p> </td> </tr><tr><td> <p class="表格單元格"><code>1.23e4</code></p> </td> <td> <p class="表格單元格">浮點小數的指數表示法(1.23×10 的4 次冪=12300.0)</p> </td> </tr><tr><td> <p class="表格單元格"><code>1.23e-4</code></p> </td> <td> <p class="表格單元格">浮點小數的指數表示法(1.23×10 的-4 次冪=0.000123)</p> </td> </tr></tbody></table> 單純的數字羅列表示 10 進制整數。以 `0b` 開頭的數值表示 2 進制數,以 `0` 或者 `0o` 開頭的數值表示 8 進制數,以 `0d` 開頭的數值表示 10 進制數,以 `0x` 開頭的數值表示 16 進制數。字面量中的 `_` 會被自動忽略。因此,在使用每 3 位數字間隔一下這樣的數值表示方法時會十分方便。 ~~~ p 1234567 #=> 1234567 p 1_234_567 #=> 1234567 p 0b11111111 #=> 255 p 01234567 #=> 342391 p 0x12345678 #=> 305419896 ~~~ 包含小數點的數值為浮點小數。我們還可以采用有效數字與指數配合的科學計數法來表示浮點小數。格式為“有效數字”+“英文字母 e(或者 E)”+“表示指數的整數”。 ~~~ p 1.234 #=> 1.234 p 1.234e4 #=> 12340.0 p 1234e-4 #=> 0.0001234 ~~~ ### **12.3 算數運算** 表 12.2 列出的是數值對象間進行基本的算術運算時用到的運算符。 **表 12.2 算數運算的運算符** <table border="1" data-line-num="112 113 114 115 116 117 118 119 120" width="90%"><thead><tr><th> <p class="表頭單元格">運算符</p> </th> <th> <p class="表頭單元格">運算</p> </th> </tr></thead><tbody><tr><td> <p class="表格單元格"><code>+</code></p> </td> <td> <p class="表格單元格">加法運算</p> </td> </tr><tr><td> <p class="表格單元格"><code>-</code></p> </td> <td> <p class="表格單元格">減法運算</p> </td> </tr><tr><td> <p class="表格單元格"><code>*</code></p> </td> <td> <p class="表格單元格">乘法運算</p> </td> </tr><tr><td> <p class="表格單元格"><code>/</code></p> </td> <td> <p class="表格單元格">除法運算</p> </td> </tr><tr><td> <p class="表格單元格"><code>%</code></p> </td> <td> <p class="表格單元格">取余運算</p> </td> </tr><tr><td> <p class="表格單元格"><code>**</code></p> </td> <td> <p class="表格單元格">乘方運算</p> </td> </tr></tbody></table> `Integer` 對象與 `Float` 對象的運算結果為 `Float` 對象。`Integer` 對象之間、`Float` 對象之間的運算結果分別為 `Integer` 對象、`Float` 對象。 ~~~ p 1 + 1 #=> 2 p 1 + 1.0 #=> 2.0 p 2 - 1 #=> 1 p 2 - 1.0 #=> 1.0 p 3 * 2 #=> 6 p 3 * 2.0 #=> 6.0 p 3 * -2.0 #=> -6,0 p 5 / 2 #=> 2 p 5 / 2.0 #=> 2.5 p 5 % 2 #=> 1 p 5 % 2.0 #=> 1.0 p 5 ** 2 #=> 25 p 5 ** 0.5 #=> 2.23606797749979 p 5 ** -2.0 #=> 0.04 p 5 ** -2 #=> 0.04 ~~~ 這里需要注意的是,指數為負整數的乘方返回的結果是表示有理數的 `Rational` 對象。 ~~~ p 5 ** -2.0 #=> 0.04 p 5 ** -2 #=> (1/25) ~~~ ### **除法** 除了 / 和 % 以外,數值對象中還有一些與除法相關的方法。 - ***x*.`div`(*y*)** 返回 *x* 除以 *y* 后的商的整數。 ~~~ p 5.div(2) #=> 2 p 5.div(2.2) #=> 2 p -5.div(2) #=> -3 p -5.div(2.2) #=> -3 ~~~ - ***x*.`quo`(*y*)** 返回 *x* 除以 *y* 后的商,如果 *x*、*y* 都是整數則返回 `Rational` 對象。 ~~~ p 5.quo(2) #=> (5/2) p 5.quo(2.2) #=> 2.2727272727272725 p -5.quo(2) #=> (-5/2) p -5.quo(2.2) #=> -2.2727272727272725 ~~~ - ***x*.`modulo`(*y*)** 與 `x % y` 等價。 - ***x*.`divmod`(*y*)** 將 *x* 除以 *y* 后的商和余數作為數組返回。商是將 *x* / *y* 的結果去掉小數點后的部分而得到的值。余數的符號與 *y* 的符號一致,余數的值為 *x* % *y* 的結果。假設有運算式如下, *ans*`=`*x*.`divmod(`*y*`)` 這時,下面的等式是成立的。 *x*`==`*ans*`[0] *`*y* + *ans*`[1]` ~~~ p 10.divmod(3.5) #=> [2, 3.0] p 10.divmod(-3.5) #=> [-3, -0.5] p -10.divmod(3.5) #=> [-3, 0.5] p -10.divmod(-3.5) #=> [2, -3.0] ~~~ - ***x*.`remainder`(*y*)** 返回 *x* 除以 *y* 的余數,結果的符號與 *x* 的符號一致。 ~~~ p 10.remainder(3.5) #=> 3.0 p 10.remainder(-3.5) #=> 3.0 p -10.remainder(3.5) #=> -3.0 p -10.remainder(-3.5) #=> -3.0 ~~~ 另外,除數為 0 時,`Integer` 類會返回錯誤,而 `Float` 類則會返回 `Infinity`(無限大)或者 `NaN`(Not a Number)。如果再用這兩個值進行運算,那么結果只會返回 `Infinity` 或者 `NaN`。程序把輸入的數據直接用于運算的時候,除數有可能會為 0,我們應當注意避免這樣的情況發生。 ~~~ p 1 / 0 #=> 錯誤(ZeroDivisionError) p 1 / 0.0 #=> Infinity p 0 / 0.0 #=> NaN p 1.divmod(0) #=> 錯誤(ZeroDivisionError) p 1.divmod(0.0) #=> 錯誤(FloatDomainError) ~~~ ### **12.4 Math 模塊** `Math` 模塊提供了三角函數、對數函數等常用的函數運算的方法。該模塊中定義了模塊函數和常量,例如,求平方根時,可以采用下述方法。 ~~~ p Math.sqrt(2) #=> 1.4142135623730951 ~~~ 表 12.3 為 Math 模塊定義的方法。 **表 12.3 Math 模塊定義的方法** <table border="1" data-line-num="208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236" width="90%"><thead><tr><th> <p class="表頭單元格">方法名</p> </th> <th> <p class="表頭單元格">作用</p> </th> </tr></thead><tbody><tr><td> <p class="表格單元格"><code>acos(<em>x</em>)</code></p> </td> <td> <p class="表格單元格">反余弦函數</p> </td> </tr><tr><td> <p class="表格單元格"><code>acosh(<em>x</em>)</code></p> </td> <td> <p class="表格單元格">反雙曲余弦函數</p> </td> </tr><tr><td> <p class="表格單元格"><code>asin(<em>x</em>)</code></p> </td> <td> <p class="表格單元格">反正弦函數</p> </td> </tr><tr><td> <p class="表格單元格"><code>asinh(<em>x</em>)</code></p> </td> <td> <p class="表格單元格">反雙曲正弦函數</p> </td> </tr><tr><td> <p class="表格單元格"><code>atan(<em>x</em>)</code></p> </td> <td> <p class="表格單元格">反正切函數</p> </td> </tr><tr><td> <p class="表格單元格"><code>atan2(<em>x</em>, <em>y</em>)</code></p> </td> <td> <p class="表格單元格">表示 4 個象限的反正切函數</p> </td> </tr><tr><td> <p class="表格單元格"><code>atanh(<em>x</em>)</code></p> </td> <td> <p class="表格單元格">反雙曲正切函數</p> </td> </tr><tr><td> <p class="表格單元格"><code>cbrt(<em>x</em>)</code></p> </td> <td> <p class="表格單元格">立方根</p> </td> </tr><tr><td> <p class="表格單元格"><code>cos(<em>x</em>)</code></p> </td> <td> <p class="表格單元格">余弦函數</p> </td> </tr><tr><td> <p class="表格單元格"><code>cosh(<em>x</em>)</code></p> </td> <td> <p class="表格單元格">雙曲余弦函數</p> </td> </tr><tr><td> <p class="表格單元格"><code>erf(<em>x</em>)</code></p> </td> <td> <p class="表格單元格">誤差函數</p> </td> </tr><tr><td> <p class="表格單元格"><code>erfc(<em>x</em>)</code></p> </td> <td> <p class="表格單元格">余補誤差函數</p> </td> </tr><tr><td> <p class="表格單元格"><code>exp(<em>x</em>)</code></p> </td> <td> <p class="表格單元格">指數函數</p> </td> </tr><tr><td> <p class="表格單元格"><code>frexp(<em>x</em>)</code></p> </td> <td> <p class="表格單元格">把一個浮點數分解為尾數和指數</p> </td> </tr><tr><td> <p class="表格單元格"><code>gamma(<em>x</em>)</code></p> </td> <td> <p class="表格單元格">伽瑪函數</p> </td> </tr><tr><td> <p class="表格單元格"><code>hypot(<em>x</em>, <em>y</em>)</code></p> </td> <td> <p class="表格單元格">計算三角形的斜邊長度</p> </td> </tr><tr><td> <p class="表格單元格"><code>ldexp(<em>x</em>, <em>y</em>)</code></p> </td> <td> <p class="表格單元格">返回 <em>x</em> 乘以 2 的 <em>y</em> 次冪的值</p> </td> </tr><tr><td> <p class="表格單元格"><code>lgamma(<em>x</em>)</code></p> </td> <td> <p class="表格單元格">伽馬函數的自然對數</p> </td> </tr><tr><td> <p class="表格單元格"><code>log(<em>x</em>)</code></p> </td> <td> <p class="表格單元格">底數為 e 的對數(自然對數)</p> </td> </tr><tr><td> <p class="表格單元格"><code>log10(<em>x</em>)</code></p> </td> <td> <p class="表格單元格">底數為 10 的對數(常用對數)</p> </td> </tr><tr><td> <p class="表格單元格"><code>log2(<em>x</em>)</code></p> </td> <td> <p class="表格單元格">底數為 2 的對數</p> </td> </tr><tr><td> <p class="表格單元格"><code>sin(<em>x</em>)</code></p> </td> <td> <p class="表格單元格">正弦函數</p> </td> </tr><tr><td> <p class="表格單元格"><code>sinh(<em>x</em>)</code></p> </td> <td> <p class="表格單元格">雙曲正弦函數</p> </td> </tr><tr><td> <p class="表格單元格"><code>sqrt(<em>x</em>)</code></p> </td> <td> <p class="表格單元格">平方根</p> </td> </tr><tr><td> <p class="表格單元格"><code>tan(<em>x</em>)</code></p> </td> <td> <p class="表格單元格">正切函數</p> </td> </tr><tr><td> <p class="表格單元格"><code>tanh(<em>x</em>)</code></p> </td> <td> <p class="表格單元格">雙曲正切函數</p> </td> </tr></tbody></table> 另外,`Math` 模塊還定義了表 12.4 的常量。 **表 12.4 Math 模塊定義的常量** <table border="1" data-line-num="241 242 243 244 245" width="90%"><thead><tr><th> <p class="表頭單元格">常量名</p> </th> <th> <p class="表頭單元格">作用</p> </th> </tr></thead><tbody><tr><td> <p class="表格單元格"><code>PI</code></p> </td> <td> <p class="表格單元格">圓周率(3.141592653589793)</p> </td> </tr><tr><td> <p class="表格單元格"><code>E</code></p> </td> <td> <p class="表格單元格">自然對數的底數(2.718281828459045)</p> </td> </tr></tbody></table> ### **12.5 數值類型轉換** 將 `Integer` 對象轉換為 `Float` 對象時,可以使用 `to_f` 方法。相反,使用 `to_i` 方法則可以將 `Float` 對象轉換為 `Integer` 對象(`Integer#to_i` 方法和 `Float#to_f` 方法返回與接收者一樣的值)。另外,也可以把字符串轉換為數值。 ~~~ p 10.to_f #=> 10.0 p 10.8.to_i #=> 10 p -10.8.to_i #=> -10 p "123".to_i #=> 123 p "12.3".to_f #=> 12.3 ~~~ `Float#to_i` 方法返回的結果會把小數點以后的值去掉。我們用 `round` 方法對小數進行四舍五入的處理。 ~~~ p 1.2.round #=> 1 p 1.8.round #=> 2 p -1.2.round #=> -1 p -1.8.round #=> -2 ~~~ 返回比接收者大的最小整數用 `ceil` 方法,返回比接收者小的最大整數用 `floor` 方法。 ~~~ p 1.5.ceil #=> 2 p -1.5.ceil #=> -1 p 1.5.floor #=> 1 p -1.5.floor #=> -2 ~~~ 我們還可以將數值轉換為 `Rational` 對象和 `Complex` 對象,分別使用 `to_r` 和 `to_c` 方法,如下所示。 ~~~ p 1.5.to_r #=> (3/2) p 1.5.to_c #=> (1.5+0i) ~~~ ### **12.6 位運算** `Interger` 類可以進行表 12.5 所示的位運算。 **表 12.5 Integer 類的位運算符** <table border="1" data-line-num="281 282 283 284 285 286 287 288 289" width="90%"><thead><tr><th> <p class="表頭單元格">運算符</p> </th> <th> <p class="表頭單元格">運算</p> </th> </tr></thead><tbody><tr><td> <p class="表格單元格"><code>~</code></p> </td> <td> <p class="表格單元格">按位取反(一元運算符)</p> </td> </tr><tr><td> <p class="表格單元格"><code>&amp;</code></p> </td> <td> <p class="表格單元格">按位與</p> </td> </tr><tr><td> <p class="表格單元格"><code>|</code></p> </td> <td> <p class="表格單元格">按位或</p> </td> </tr><tr><td> <p class="表格單元格"><code>^</code></p> </td> <td> <p class="表格單元格">按位異或 <code>((a&amp;~b|~a&amp;b))</code></p> </td> </tr><tr><td> <p class="表格單元格"><code>&gt;&gt;</code></p> </td> <td> <p class="表格單元格">位右移</p> </td> </tr><tr><td> <p class="表格單元格"><code>&lt;&lt;</code></p> </td> <td> <p class="表格單元格">位左移</p> </td> </tr></tbody></table> ~~~ def pb(i) # 使用printf 的%b 格式 # 將整數的末尾8 位用2 進制表示 printf("%08b\n", i & 0b11111111) end b = 0b11110000 pb(b) #=> 11110000 pb(~b) #=> 00001111 pb(b & 0b00010001) #=> 00010000 pb(b | 0b00010001) #=> 11110001 pb(b ^ 0b00010001) #=> 11100001 pb(b >> 3) #=> 00011110 pb(b << 3) #=> 10000000 ~~~ > **專欄** > **位與字節** > 在計算機的世界中,我們經常會接觸到“位”與“字節”,接下來我們就來介紹一下它們所代表的意義。 > - > **位(bit)** > 位是計算機中最小的數據單位,表示 ON 或 OFF,或者 0 或 1。據說原本是“Binary digit”的簡稱。 > - > **位與 2 進制** > 雖然位中只包含兩種信息,但將位的信息兩兩組合的話,就可以表示 00、01、10、11 這四種信息。同樣,3 位一組的話可以表示八種信息,4 位一組的話可以表示十六種信息。隨著位的數量的增加,可以表示的信息的數量也會成倍的增加。 > 像這樣,只用 0 和 1 的計數方式稱為 2 進制。我們一般使用的計數方式是 10 進制,這種計數方式總共可表示從 0 到 9 十個數。下面是 2 進制與 10 進制的對照表。 > **表 10 進制、2 進制、8 進制、16 進制對照表** | 10 進制 | 2 進制 | 8 進制 | 16 進制 | |-----|-----|-----|-----| | `?0` | `????0` | `?0` | `?0` | | `?1` | `????1` | `?1` | `?1` | | `?2` | `???10` | `?2` | `?2` | | `?3` | `???11` | `?3` | `?3` | | `?4` | `??100` | `?4` | `?4` | | `?5` | `??101` | `?5` | `?5` | | `?6` | `??110` | `?6` | `?6` | | `?7` | `??111` | `?7` | `?7` | | `?8` | `?1000` | `10` | `?8` | | `?9` | `?1001` | `11` | `?9` | | `10` | `?1010` | `12` | `?A` | | `11` | `?1011` | `13` | `?B` | | `12` | `?1100` | `14` | `?C` | | `13` | `?1101` | `15` | `?D` | | `14` | `?1110` | `16` | `?E` | | `15` | `?1111` | `17` | `?F` | | `16` | `10000` | `20` | `10` | | `17` | `10001` | `21` | `11` | > - > **8 進制與 16 進制** > 計算機處理的信息是用 2 進制表示的。但是如果全部都只用 0、1 來表示的話,位數就會變得非常大,不便于人們理解。因此就可以使用 8 進制和 16 進制來解決這個問題。8 進制使用 0 到 7 共 8 個數,用 1 位數表示 3 個位(bit)。16 進制使用 0 到 15 共 16 個數,用 1 位數表示 4 個位(bit)。由于一般我們使用的數字只有 10 個,因此在 16 進制中,10 到 15 之間的數字就用英文字母 A 到 F 表示。 > - > **字節(byte)** > 計算機在表示數的時候,會把一定數量的位(bit)的組合——字節作為計數單位。一個字節有多少位并沒有共通的標準。在以前,根據制造商和機種的不同,1 個字節包含的位的數量也不一樣,但現在 1 個字節有 8 位已經是業界的常識了。1 個字節可以表示的 10 進制數是從 0 到 255,8 進制數是從 000 到 377,16 進制數是從 00 到 FF。由于 2 個 16 進制位剛好等于 8 位(1 個字節),因此用 16 進制來表示以字節為單位的數據會非常方便。 ### **12.7 隨機數** 有時候隨機性可能會幫助我們解決一些問題。隨機性一般有以下特質。 - **沒有規則和法則依據** - **一定范圍內的數會均等地出現** 拿擲骰子為例,我們不能預測下一個投出的是哪一面,但骰子各個面投出的幾率都是一樣的。我們把這樣的情況稱為隨機,隨機得到的數值稱為隨機數。在擲骰子或者洗撲克牌那樣需要偶然性的情況下,或者像加密后的密碼那樣希望得到一些難以被預測的數據時,一般都會用到隨機數。 我們可以用 `Random.rand` 方法得到隨機數。不指定參數時,`Random.rand` 方法返回比 1 小的浮點小數。參數為正整數時,返回 0 到該正整數之間的數值。 ~~~ p Random.rand #=> 0.13520495197709 p Random.rand(100) #=> 31 p Random.rand(100) #=> 84 ~~~ 程序不能生成真正的隨機數,只能通過某種算法生成看起來像隨機數的值,這樣的隨機數稱為模擬隨機數。生成模擬隨機數需要以某個值為基礎,這個值稱為隨機數的種子。模擬隨機數終究只是通過計算得到的數值,只要隨機數的種子一樣,那么得到值就有可能重復出現。使用 `Random.new` 方法初始化隨機數生成器,然后再使用 `Random#rand` 方法,就可以對 `Random` 對象指定隨機數種子,從而生成隨機數。 ~~~ r1 = Random.new(1) # 初始化隨機數組 p [r1.rand, r1.rand] #=> [0.417022004702574, 0.7203244934421581] r2 = Random.new(1) # 再次初始化隨機數組 p [r2.rand, r2.rand] #=> [0.417022003702574, 0.7203244934421581] ~~~ `Random.new` 方法不指定參數的情況下,則會用隨機生成的隨機數種子初始化 `Random` 對象,因此每次得到的隨機數組也會不一樣。 ~~~ r1 = Random.new p [r1.rand, r1.rand] #=> [0.49452535392946817, 0.34141702823098863] r2 = Random.new p [r2.rand, r2.rand] #=> [0.9464262066747281, 0.01911968591048996] ~~~ 在信息安全領域中,“優質的隨機”是一個重要的課題。生成用于加密 key 的隨機數時,不能重復出現是非常重要的,因此就需要我們慎重地選擇難以被預測的隨機種子。在一些特殊的情況下可能會需要初始化 `Random` 對象,而一般情況下直接用最開始介紹的 `Random.rand` 方法就足夠了。 ### **12.8 計數** 除了數值計算外,`Integer` 類還能計算處理的次數、數組的元素個數等。接下來介紹的方法就是按照數值指定的次數執行循環處理的迭代器。 - ***n*.`times`{|*i*| … }** 循環 *n* 次,從 0 到 *n*-1 的值會被依次賦值給塊變量。 ~~~ ary = [] 10.times do |i| ary << i end p ary #=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] ~~~ - ***from*.`upto`(*to*){|*i*| … }** 從 *from* 開始循環對 *i* 進行加 1 處理,直到 *i* 等于 to。*from* 比 *to* 大時不會執行循環處理。 ~~~ ary = [] 2.upto(10) do |i| ary << i end p ary #=> [2, 3, 4, 5, 6, 7, 8, 9, 10] ~~~ - ***from*.`downto`(*to*){…}** 從 *from* 開始循環對 *i* 進行減 1 處理,直到 *i* 等于 *to*。*from* 比 *to* 小時不會執行循環處理。 ~~~ ary = [] 10.downto(2) do |i| ary << i end p ary #=> [10, 9, 8, 7, 6, 5, 4, 3, 2] ~~~ - ***from*.`step`(*to*, *step*){…}** 從 *from* 開始循環對 *i* 進行加 *step* 處理,直到 *i* 等于 *to*。*step* 為正數時,*from* 比 *to* 大時不會執行循環處理。*step* 為負數時,*from* 比 *to* 小時不會執行循環處理。 ~~~ ary = [] 2.step(10, 3) do |i| ary << i end p ary #=> [2, 5, 8]   ary = [] 10.step(2, -3) do |i| ary << i end p ary #=> [10, 7, 4] ~~~ 如果不對 `times`、`upto`、`downto`、`step` 的各方法指定塊,則會返回 `Enumerator` 對象。這樣,之前通過 `step` 方法的塊獲取的一連串數值,就同樣也可以通過 `Enumerator#collect` 方法獲取。關于 `Enumerator` 對象,我們會在第 14 章中介紹。 ~~~ ary = 2.step(10).collect{|i| i * 2} p ary #=> [4, 6, 8, 10, 12, 14, 16, 18, 20] ~~~ ### **12.9 近似值誤差** 處理浮點小數時很容易因誤差產生問題。這里我們來看看具體的例子,執行下面的程序后會產生意想不到的結果。 ~~~ a = 0.1 + 0.2 b = 0.3 p [a, b] #=> [0.3, 0.3] p a == b #=> false ~~~ 雖然我們期待 0.1 + 0.2 與 0.3 的比較結果為 `true`,但實際結果卻是 `false`。為什么會這樣呢? 在 10 進制中,就像 1/10、1/100、1/1000……這樣,我們會用 10 取冪后的倒數來表示數值。而另一方面,`Float` 類的浮點小數則是用 2 取冪后的倒數來表示,如 1/2、1/4、1/8……。因此,在處理 1/5、1/3 這種用 2 進制無法正確表示的數值時,結果就會產生誤差。而如果要用 2 進制的和來表示這類數值的話,計算機就必須在適當的位置截斷計算結果,這樣就產生了近似值誤差。 如果可以把小數轉換為兩個整數相除的形式,那么通過使用 `Rational` 類進行運算,就可以避免近似值誤差。 ~~~ a = Rational(1, 10) + Rational(2, 10) b = Rational(3, 10) p [a, b] #=> [(3/10), (3/10)] p a == b ~~~ 另外,Ruby 還提供了 `bigdecimal` 庫,可以有效處理擁有更多小數位的 10 進制數。 > **專欄** > **Comparable 模塊** > Ruby 的比較運算符(`==`、`<=` 等)實際上都是方法。`Comparable` 模塊里封裝了比較運算符,將其 Mix-in 到類后,就可以實現實例間互相比較的方法(下表)。Comparable 在英語中就是“可以比較”的意思。 > **表 Comparable 模塊封裝的方法** | | `<>` | `==` | `>=` | `>` | `between?` | |-----|-----|-----|-----|-----|-----| > `Comparable` 模塊中的各運算符都會使用 `<=>` 運算符的結果。`<=>` 運算符如果能像下表那樣定義的話,上表中的各個方法就都可以使用。 > **表 表 a <=> b 的結果** | `a <>`時 | -1( 比0 小) | |-----|-----| | `a == b`時 | 0 | | `a > b`時 | 1(比 0 大) | > 下面的 `Vector` 類表示擁有 *x* 和 *y* 兩個坐標的向量。為了比較向量間的坐標,這里定義了 `<=>` 運算符。然后,通過包含(include)`Comparable` 模塊,就可以實現上表中的比較方法。 ~~~ class Vector include Comparable attr_accessor :x, :y   def initialize(x, y) @x, @y = x, y end   def scalar Math.sqrt(x ** 2 + y ** 2) end   def <=> (other) scalar <=> other.scalar end end   v1 = Vector.new(2, 6) v2 = Vector.new(4, -4) p v1 <=> v2 #=> 1 p v1 < v2 #=> false p v1 > v2 #=> true ~~~ > 在本書介紹過的類中,`Numeric`、`String`、`Time` 都包含了 `Comparable` 模塊。 ### **練習題** 1. 表示溫度的單位有攝氏、華氏兩種。請定義將攝氏轉換為華氏的方法 `cels2fahr`。攝氏與華氏的轉換公式如下: **華氏=攝氏 × 9 ÷ 5 + 32** 2. 與 1 相反,請定義將華氏轉換為攝氏的方法 `fahr2cels`。然后從 1 攝氏度到 100 攝氏度,請按照每隔 1 攝氏度輸出一次的方式,輸出對應的華氏溫度。 3. 請定義返回擲骰子(1 到 6 隨機整數)的結果的 `dice` 方法。 4. 請定義合計擲 10 次骰子的結果的 `dice10` 方法。 5. 請定義調查整數 `num` 是否為素數的 `prime?(num)` 方法。素數的定義為除了 1 和自己外不能被整除的數。個位整數中,2、3、5、7 為素數。 > 參考答案:請到圖靈社區本書的“隨書下載”處下載([http://www.ituring.com.cn/book/1237](http://www.ituring.com.cn/book/1237))。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看