2015-09-01 35 views
3

我目前正在Scala工作,並越來越驚訝它有多好。 一位偉大的點,我認爲是如何處理BigDecimal type.Once定義BigDecimal你可以使用它幾乎一樣,如果它是IntDouble寫BigDecimal計算就好像它只是一個普通的四個算術運算在斯卡拉

val foo:BigDecimal = 0.1 
println(foo + 0.2) // 0.3 

沒有必要使用.multiply().add()而只是+*來處理BigDecimal Calculation(我假設BigDecimal+/*最終會在它內部調用它們)。即使計算變得複雜,也很容易閱讀,除非您必須聲明第一個計算值爲BigDecimal

println(0.3 * (BigDecimal(0.1) + 0.2)) 

我的問題是,我怎麼能寫這樣的代碼?

println(0.3 * (0.1 + 0.2)) 

我認爲這需要重寫數字類型文字。

在此先感謝。

回答

6

我不認爲你可以重寫數字文字。你可以做的是使用字符串插值或者向Double添加方法來簡化語法。

// With string interpolation 
implicit class BigDecimalStringContext(private val sc: StringContext) extends AnyVal { 
    def d(args: Any*): BigDecimal = { 
    val stringRepr = sc.s(args: _*) 
    BigDecimal(stringRepr) 
    } 
} 

println(d"0.3" * (d"0.1" + d"0.2")) 
println(0.3 * (d"0.1" + 0.2)) 


// Pimp my library 
implicit class DoubleOps(private val d: Double) extends AnyVal { 
    def bd = BigDecimal(d) 
} 

println(0.3.bd * (0.1.bd + 0.2.bd)) 
println(0.3 * (0.1.bd + 0.2)) 

第一種方法是更安全的,因爲第二個嘗試將Double轉換,因此可能會失去精度:

scala> 0.123456789.bd * (0.1.bd + 0.2.bd) 
res1: scala.math.BigDecimal = 0.037037036703703704 

scala> d"0.123456789" * (d"0.1" + d"0.2") 
res2: scala.math.BigDecimal = 0.0370370367037037036703703703670 
+0

我同意你展示的「Pimp my library」方法。你甚至可以把它寫成'println(0.3 bd *(0.1 bd + 0.2 bd))',這可能更好看,主觀。 – mattinbits

2

Scala沒有允許覆蓋文字,很遺憾。

有一兩件事你可以很容易地從語言正確內完成,將提供自己的StringContextstring interpolation

implicit class BigDecimalStringContext(val sc: StringContext) extends AnyVal { 
    def d() = BigDecimal(sc.parts.head) 
} 

val test = d"0.1" 
// => test: scala.math.BigDecimal = 0.1 

相信Macros不允許您覆蓋文字。

Scala-Virtualized是Scala的一個分支,其中(幾乎)所有東西(包括控制結構和對象構造)轉換爲方法調用,因此可能會被重載。不幸的是,差不多一切都不包含重載文字。

但是,您可能可以使用Compiler Plugin進行操作。

+1

該死的,我遲到了:-D –

+0

我把upvoted的答案無論如何:) –