標籤:支援 模式比對 nbsp var row 處理 乘法 群組類型 container
一、前言
前面已經學習了Scala中的String,接著學習Scala的Numbers。
二、Numbers
在Scala中,所有的數字類型,如Byte,Char,Double,Float,Int,Long,Short都是對象,這七種數字類型繼承AnyVal特質,這七種數字類型與其在Java中有相同的範圍,而Unit和Boolean則被認為是非數字實值型別,Boolean有false和true兩個值,你可以擷取到各個數字類型的最值。
複雜的數字和日期
如果需要更強大的數類,可以使用spire,scalalab。
如果需要更強大的日期類,可以使用Joda Time,nscala-time。
2.1 從字串中解析數字
1. 問題
你想要將字串類型轉化為數字類型。
2. 解決方案
使用String的to*方法即可將String轉化為相應的數字。
當無法進行轉化時,to*方法可能會拋出NumberFormatException異常。
可以直接使用字串來建立BigInt和BigDecimal執行個體(也可能會拋出異常)
處理基和基數
如果在計算時不以10為基(十進位)進行計算,而要使用其他進位,此時Int類的toInt方法不允許傳入基和基數,此時需要使用parseInt方法,parseInt可將字串轉化為在指定進位下的值
也可以使用隱式轉化來完成上述的功能
3. 討論
由於在Scala中沒有受檢查異常,因此你不需要在方法中聲明throws NumberFormatException。但是為了使調用者明白該方法可能會拋出異常,你可以使用throws註解
@throws(classOf[NumberFormatException])def toInt(s: String) = s.toInt
更通常而言,在Scala中使用Option/None/Some進行模式比對來處理
def toInt(s: String):Option[Int] = { try { Some(s.toInt) } catch { case e: NumberFormatException => None }}
此時你就可以使用不同的方法來調用toInt方法
println(toInt("1").getOrElse(0)) // 1println(toInt("a").getOrElse(0)) // 0
另外一種使用方法就是使用匹配運算式
toInt(aString) match { case Some(n) => println(n) case None => println("Boom! That wasn‘t a number.")}
也可以使用如下直接提取出值
val result = toInt(aString) match { case Some(x) => x case None => 0 }
2.2 數字類型間的轉化
1. 問題描述
你想要從一種數字類型轉化為另一種數字類型,如從Int到Double。
2. 解決方案
不同於Java使用cast方法,Scala中可以直接使用數字類型提供的to*方法。
3. 討論
在Java中,需要強制轉化來將double類型轉化為int類型
int a = (int) 100.00;
但是在Scala中,使用to*方法即可完成上述轉化,如果你想要避免轉化錯誤,你可以使用isValid方法來測試是否可以轉化
2.3 重寫預設類型
1. 問題描述
當你給變數賦值時,Scala會自動給變數賦予相應的類型,當你建立數字欄位時,你需要重寫預設的類型。
2. 解決方案
如果你將1賦值給變數a,那麼a預設為Int類型
下面例子重寫了預設類型
另一種方法是用類型注釋變數
也可以在等號左邊進行定義
你也可以在數字前面添加0x或0X來建立十六進位整形
3. 討論
當建立對象執行個體時,應該注意如下文法結構
var [name]:[Type] = [initial value]
在初始化數字類型的var欄位時,可以使用預留位置,其值預設為0,預留位置僅僅只在類定義時有效,其他時候則不行,如在方法內部定義不起作用
class Foo { var a: Short = 0 // 定義初始值 var b: Short = _ // 預設為0}
但在方法中,可以使用如下方法
var name = null.asInstanceOf[String]
當然更好的辦法是使用Option/None/Some模式比對,這樣可以避免空值
2.4 替換++、--
1. 問題描述
在其他語言中,你可以使用++、--來增1、減1,然而,在Scala中沒有++、--操作符
2. 解決方案
由於val類型變數是不可變的,所以不能進行加法或減法的操作,但是var類型是可變,可以使用+=、-=方法來進行加法或減法
同理,也可以使用*=、/=方法進行乘法、除法操作
值得注意的是+=、-=、*=、/=都不是操作符,而是方法,他們是var型Int變數上實現的方法。
3. 討論
在其他數字類型上也可以使用+=、-=、*=、/=方法
2.5 比較浮點數
1. 問題描述
你需要比較兩個浮點數,但在其他一些程式設計語言中,它們應該是相等的兩個浮點數
2. 解決方案
在Java和許多其他語言,你可以通過建立一個指定比較精度的方法來決這個問題,下面是約等於方法
def ~=(x: Double, y: Double, precision: Double) = { if ((x - y).abs < precision) true else false}
3. 討論
當進行浮點數計算時,0.1 + 0.1等於0.2,但是0.1 + 0.2不等於0.3
這種細小的錯誤使得比較兩個浮點數成為真正的問題。
因此,你需要自訂比較精度的函數來比較兩個浮點數是否相等,你可以定義隱式轉化,然後在需要是引入即可。或者將方法放在object對象中,這樣可以直接調用
object MathUtils { def ~=(x: Double, y: Double, precision: Double) = { if ((x - y).abs < precision) true else false}
然後直接通過MathUtils調用~=方法進行比較
println(MathUtils.~=(a, b, 0.000001))
2.6 處理大數
1. 問題描述
你正在編寫需要使用非常大的整數或十進位數的應用程式
2. 解決方案
你可以使用BigInt或BigDecimal類
不同於其在Java的對應類,這些類支援所有你使用數字類型的操作符
你也可以把它們轉化為其他數字類型
為了避免錯誤,也可以在轉化之前進行測試
3. 討論
雖然Scala中的BigInt和BigDecimal是由Java中的BigInt和BigDecimal支援的,但是Scala中的類使用更為簡便,並且它們是可變的,可以像其他數字類型一樣操作。
2.7 產生隨機數
1. 問題描述
你需要建立隨機數,如測試應用程式、執行類比以及許多其他情況
2. 解決方案
使用scala.util.Random來建立隨機數
你可以指定隨機產生數位最大值
上述樣本將會產生[0-99]之間的數字,你也可以產生隨機Float(0.0到1.0之間的浮點數)
也可以產生隨機Double(0.0到1.0之間的浮點數)
你也可以在建立Random時指定seed值,也可以之後調用setSeed方法進行設定
3. 討論
Random類可以應對所有通常的使用,包括產生數字、設定最大值、設定seed值,也可以產生隨機字元
Scala可以產生一段隨機長度的數字,在測試時非常有用
也可以產生隨機長度的浮點數
2.8 建立數字範圍,列表或數組
1. 問題描述
你需要建立一個數字範圍、列表或數組,如for迴圈或用於測試目的
2. 解決方案
使用Int類的方法來建立一個數字Range
也可以自訂間距
3. 討論
在Scala中可以很輕易的建立數字範圍,並且可以很輕易的將其轉化為列表或者數群組類型
更好的方式如下
2.9 格式化數字和貨幣
1. 問題描述
你想要格式化數字和貨幣來控制小數點和逗號,特別是用於列印輸出。
2. 解決方案
對於簡單的數字格式化,可以採用前篇博文提到的f字串插值
添加逗號的一種簡單方法是調用java.text.NumberFormat類的getIntegerInstance方法
在使用getIntegerInstance方法的時候可以指定地區
在處理浮點數時可以使用getInstance方法
對於貨幣格式,可以使用getCurrencyInstance方法
下面方法可以處理國際化貨幣
3. 討論
主要討論了使用Java的相關類來格式化數字和貨幣,也可以使用BigDecimal來處理貨幣的格式問題。
三、總結
本篇博文學習了數字類的相關操作,可以看到Scala相比於Java簡易很多,與Java也是無縫相容的。也謝謝各位園友的觀看~
【Scala】Scala之Numbers