4 2 2 計算資料

2021-06-26 06:26:49 字數 3161 閱讀 4706

4.2.2 計算資料

在這個應用程式的第乙個版本中,我們將只列印標籤,以及圖表中每一項所佔比例(百分比)。

要計算百分比,就需要知道列表中所有專案數值總和,這個值用清單 4.4 中的函式 calculatesum 來計算。

清單 4.4 計算列表中的數值和 (f# interactive)

> let rec calculatesum(rows) =

matchrows with | -> 0  <-- 空列表返回 0

| (_, value)::tail ->    [1]

let remainingsum = calculatesum(tail)  <-- 遞迴計算列表尾元素的和

value + remainingsum

val calculatesum : ('a * int) list ->int

> let sum = calculatesum(testdata);;

val sum : int = 579

> 123.0 / float(sum) * 100.0;;  [2]

val it : float = 21.24352332

這個函式再次展示了處理列表的遞迴模式。如果我們還反覆寫同樣的模式**,可能會出錯了(重複既無樂趣,也無聊);理想情況下,只應該寫每個版本的獨特部分的**,我們自己不需要重複。對前面的示例,這個異議是有效的,我們可寫得更簡潔,在後面的章節將學習如何實現。在許多函式程式中,仍然需要遞迴與模式匹配,所以,看看另外的示例並熟悉概念是很有用的。

對於空列表,函式 calculatesum 只返回 0;對於 cons cell,以遞迴方式對列表尾(原始列表減去第乙個元素)中的值求和,然後,把這個結果加到頭(列表中的第一項)中的值上。這段**中的模式配,演示了乙個值得討論的重要模式。在第二個分支中[1],我們需要分解 cons cell,因此,按照 head::tail 模式,匹配列表。但是,**比這個要更複雜一些,因為在同時,還要根據分解元組,寫作 (first, second) 的模式,匹配列表頭。這是因為,列表包含了元組,第乙個引數是標題,第二個引數是數值。在示例中,我們只要讀數值,而忽略標題,因此,使用下劃線模式忽略元組的第乙個成員。如果我們把所有這些模式組合在一起,就得到 (_, value)::tail,這就是我們在**中所使用的。

從 f# interactive 所輸出的函式簽名,可以看到,函式取乙個元組列表作為輸入,返回整數;輸入元組的型別是 'a * int,表示該函式是泛型,處理的列表可以包含任意元組,只要第二個元素是整數,第乙個元素的型別不確定,因為其值在模式匹配中被忽略。f# 編譯器自動使**泛型,這種功能稱為自動泛型化(automatic generalization)。在第五和第六章,我們將學習更多有關泛型函式與自動泛型化的內容。

清單 4.3 中的最後乙個命令[2],為在清單 4.4 中的測試鋪平了道路,那為什麼不止一次輸入測試資料呢?為了測試這個函式,先計算出和,最後,計算值為 123 的記錄所佔的百分比。因為我們想要獲得精確結果(21.24%),因此呼叫函式 float,把整數轉換為浮點數。

轉換和解析數字

f# 是一種 .net 語言,因此它使用這個平台上可用的數值型別的標準集。下面的清單顯示了我們將要用到的最有用的型別,可以看到,.net 的類名以斜體表示,f# 使用的簡稱放在括號中:

■int32,uint32 (int,uint32): 標準的 32 位整數型別;f# 中,文字寫作:42 (有符號)或 42u (無符號);也有 16 位和 64 位的變體,對於 16 位 (int16,uint16),寫作 42s 和 42us,64 位 (int64,uint64)寫作 1 l 或 64 位的 1ul。

■double, single (float, float32):表示雙精度和單精度浮點數;文字分別寫作 3.14 和 3.14f。注意,在這裡 f# 和 c# 之間是有區別的:在 c# 中的 double,在 f# 中叫 float;在 c# 中的float 在 f# 中叫 float32。

■sbyte, byte (sbyte, byte):有符號和無符號的 8 位整數;文字寫作 1y (有符號)和 1uy (無符號。

■ decimal (decimal):十進位制浮點型別,適合財務計算需要很多位整數和小數字數。文字寫作 3.14m。

■biginteger (bigint):表示任意大小的整數型別。這是 .net 4.0 中的新型別,由 system.numerics 命名空間提供;f# 的早期版本包含了這個型別的自己實現,因此,在 visual studio 2008 中開發早期版本的 .net 框架應用程式時,可以使用。在 f# 中,這種型別的文字寫作 1i。

與 c# 不同,f# 編譯器在不同的數字型別之間,即使在精度不會丟失的情況下,也不插入自動轉換;f # 也不使用型別轉換(type-cast)語法進行顯式轉換,因此,所有的轉換都必須寫成函式呼叫的形式。f# 庫提供一組轉換函式,通常與 f# 中目標型別的名稱相同。下面是幾個最有用的轉換函式:

■int :將任意數字轉換為整數;該函式是多型的(polymorphic),因此,可以處理不同的引數型別。例如,將浮點值轉換為整數,可以寫成int 3.14;將位元組值轉換為整數,寫成int 42uy。

■float, float32 :將數字轉換為雙精度或單精度浮點數;float 對應於.net 的 double 型別,float32 對應於 .net 的 single 型別,有時令人困惑。

這些函式也可以用於將字串轉換為數字。如果需要更多地控制轉換,例如,指定區域(culture)資訊,可以使用 parse 方法。此方法是system 命名空間中的 .net 類,相當於數值型別。例如,要把字串轉換成整數,可以寫成 int32.parse("42")。此方法在轉換失敗時會將丟擲異常,因此,還有乙個方法 tryparse。使用此方法,可以很容易測試轉換是否成功,該方法返回布林值標記,並通過輸出引數給出解析後的數值;但在 f# 中,我們還有更簡單的方法可以訪問,我們將在第五章詳細討論。可以看到,這種用法很簡單:

let (succ, num) = int32.tryparse (str)

if succ then console.write("succeeded:", num)

else console.write("failed")

在清單 4.4 中,我們最後計算了乙個項佔測試資料集的百分比的等式。這是 f# 迭代開發的另乙個示例,因為,這正是我們在下一節所需要的等式。我們在隔離情況下嘗試寫出了這個計算中較難的部分,這樣,可以在下一節使用。**首先從檔案中讀資料,然後,使用這個等式作為**的基礎,輸出資料集到控制台。

BigDecimal型別計算資料使用方式總結

bigdecimal bigdecimal1 newbigdecimal 1 bigdecimal bigdecimal2 newbigdecimal 1 description 加法 add bigdecimal sum bigdecimal1.add bigdecimal2 descriptio...

分組計算資料的合MSSQL

一張單位表unit id name 1 中石油 2 中移動 3 電信 另一張表info id unitid num point 1 1 1 2 2 1 2 1 3 2 1 1 4 3 2 2 若num 1時 得1分 若num 2時 得3分 若point 1時 得1分 若point 2 得3分 還有在...

1665 計算數字

中文english 給出乙個十進位制數num,現在你需要把它轉成二進位制數,並返回1的個數和位置。樣例例1 輸入 10 輸出 2,1,3 解釋 10轉成2進製為1010,總共有2個1,所以ouptput陣列第乙個是2。然後1的位置是第1個和第3個,所以後續兩個數為1,3.例2 輸入 7 輸出 3,1...