@MSkarsaune#DV14 #ScalaCalculations
Bring Your Calculations to:[email protected]
Kantega – Norwegian software craftsmanship since 2003
高馬丁
@MSkarsaune#DV14 #ScalaCalculations
1.The Situation
@MSkarsaune#DV14 #ScalaCalculations
• Exact representation of values within range
• Interoperable through widening conversion
Integer
float double byte short int long
Java Number Types - Integer
@MSkarsaune#DV14 #ScalaCalculations
• Approximate representation of numeric values
• NEVER use for monetary amounts
• Interoperable with integer types through widening
conversion
Floating point Integer
float double byte short int long
Java Number Types – Floating point
@MSkarsaune#DV14 #ScalaCalculations
• Immutable
• Calculation possible via primitives
• Interoperability through widening conversion
Floating point Integer Number
Float Double Byte Short Integer Long BigInteger BigDecimal
float double byte short int long
boxingunboxin
g
Java Number Types - Boxed
@MSkarsaune#DV14 #ScalaCalculations
• To represent large numbers
• Calculations with methods
• Cumbersome conversions
“Infinite”Floating point Integer Number
Float Double Byte Short Integer Long BigInteger BigDecimal
float double byte short int long
Java Object Number - Extended
Poor
interoperabilit
y
@MSkarsaune#DV14 #ScalaCalculations
2. Inspiration
@MSkarsaune#DV14 #ScalaCalculations
Smalltalk calculations
Numbers are objects
Binary message selectors (+, -, *, / , ….)
Built in decimals
Overflows handled
Precise division
Interoperable and extendable number types
@MSkarsaune#DV14 #ScalaCalculations
The Hope
@MSkarsaune#DV14 #ScalaCalculations
Main Scala language number types
AnyVal
Double Int Long
ScalaNumber
BigDecimal BigInt
@MSkarsaune#DV14 #ScalaCalculations
1. Decimal Numbers
@MSkarsaune#DV14 #ScalaCalculations
Decimal representation
• Integer value and scale
• 123456789
• Scale is important! Know your scale!
Scale = 3
1234567891000
@MSkarsaune#DV14 #ScalaCalculations
Decimal notation
• Smalltalk: 2.5s2
• Java: new BigDecimal("2.50")
new BigDecimal(2.5).setScale(2)
• Scala: val dec : BigDecimal = 2.50
How is this possible?
@MSkarsaune#DV14 #ScalaCalculations
Scala Implicit Type Conversion
• Implicit type conversion
• Compiler looks for implicit function to convert source type
to target type
• Object scala.math.BigDecimal:
/** Implicit conversion from `Double` to `BigDecimal`. */
implicit def double2bigDecimal(
d: Double): BigDecimal = decimal(d)
@MSkarsaune#DV14 #ScalaCalculations
Decimal computation
• Task multiply decimal dec by 100:
• Smalltalk: dec * 100
• Java: dec.multiply(new BigDecimal(100));
• Scala: dec * 100
What does this mean?
@MSkarsaune#DV14 #ScalaCalculations
Infix, symbols + implicit conversion
• Special characters as method identifiers (+ , - , ∙, √, ⊂, π
…)
• Infix notation: num.*(100) <==> num * 100
• Class scala.math.BigDecimal:
• Also works: 100 * num
/** Multiplication of BigDecimals */
def * (that: BigDecimal): BigDecimal
= new BigDecimal(
this.bigDecimal.multiply(that.bigDecimal, mc), mc)
@MSkarsaune#DV14 #ScalaCalculations
Decimal calculation summary
• Natural syntax
• Operators and literals
• Interoperable with other number types
• Withouth having to change existing number types
@MSkarsaune#DV14 #ScalaCalculations
Spire math
• Scala calculation library:
https://github.com/non/spire
• Generic algorithms
• Extended number types, such as
• Rational
• Real
• Complex
• Macros provide additional number literal syntax
@MSkarsaune#DV14 #ScalaCalculations
4. Overflow1_000_000 * 1_000_000 = ?
1_000_000_000_000 ?
-727_379_968
@MSkarsaune#DV14 #ScalaCalculations
Overflow management
• Smalltalk:
Automatically converts SmallInteger <=> LargeInteger
• Java:
Libraries such as guava or Apache commons-math can
detect
@MSkarsaune#DV14 #ScalaCalculations
(Some) Spire number types
• SafeLong detects overflows and ensures optimal
representation
ScalaNumber
SafeLong Real Rational Complex
@MSkarsaune#DV14 #ScalaCalculations
SafeLong example
val trillion : SafeLong = 1000000000000l //SafeLongLong
val product = trillion * trillion //SafeLongBigInt
val other = product / trillion //SafeLongLong
@MSkarsaune#DV14 #ScalaCalculations
3. Division2 / 3 = ?
0 ?
0.6666666666666666 ?
0.6666666666666667 ?
2
3?
@MSkarsaune#DV14 #ScalaCalculations
Precise division
• Smalltalk: 3 / 3 = 1
2 / 3 =2
3* 3 = 2
@MSkarsaune#DV14 #ScalaCalculations
(Some) Spire number types
• Real ensures exact division and always chooses the
most precise representation
ScalaNumber
SafeLong Real Rational Complex
@MSkarsaune#DV14 #ScalaCalculations
Real example
val numerator: Real = 2 //Real$Exact(2)
val fraction = numerator / 3 //Real$Exact(2/3)
fraction * 3 //Real$Exact(2)
fraction * Real.pi
//Real$Inexact(2.0943951023931954923084289221863352561314)
@MSkarsaune#DV14 #ScalaCalculations
Some conversion code of our own
….final class DoubleSyntax(val value : Double) {
def scaled(scale : Int) = BigDecimal(value).setScale(scale)
def i = Complex(0.0, value)
}
object DoubleSyntax {
implicit def doubleToDoubleConverter(value : Double) =
new DoubleSyntax(value)
}
@MSkarsaune#DV14 #ScalaCalculations
… that allows us to write
val dec : BigDecimal = 2.50
val dec = 2.5 scaled 2 // BigDecimal(2.50) “2.5s2”
val complex = -1.0 + 1.0.i // Complex(-1.0, 1.0)
@MSkarsaune#DV14 #ScalaCalculations
Conclusion
• Scala brings
• Natural syntax: special characters + infix notation
• Extendability and interoperability: implicit type conversions
• Possible improvements (as demonstrated by spire math)
• New number types
• New calculations
@MSkarsaune#DV14 #ScalaCalculations
References
http://www.scala-lang.org/
Spire:
https://github.com/non/spire
Sample code:
https://github.com/skarsaune/devoxx.scala.calculations
@MSkarsaune#DV14 #ScalaCalculations
Thank you for your time