How to perform calculation given multiple types of numbers? - scala

I have some numbers list that I go through it, and doing a simple calculation to for two numbers:
I have numberA and numberB, and the calculation im doing is:
val res = (numberA/numberB) * 100
now, I dont know what type is the number, but I know it could be float (with 2 nums after the dot) or integer...
so I want to know what is the syntax in scala to calculate it?
currently I have:
val num1 = (vatReclaimed.toInt/vatPaid.toInt) * 100
but its obviously dont work, and I cannot really use toInt i guess since I dont know the type...
whats important to me that the res will hold the right answer, so if its 2.3 * 4 the res will hold 9.2
thanksss!

When you do not know the type only, that is a number, you probably have to work with Numeric. With numeric you can convert any numeric value to Double, Float, Int or Long. For precision I would recommend Double:
def calc[A : Numeric, B : Numeric](a: A, b: B): Double = (a.toDouble / b.toDouble) * 100

Related

Multiply Double with BigDecimal

I have a BigDecimals that's always have 30 digits after the decimal points.
And I want to multiply them with Double and get a BigDecimal with 30 digits after decimal point.
For exemple I have:
val double = 4.0
val bd = 0.111111111111111111111111111111
def multiply(d : Double, bd : BigDecimal, scale: Int) = {
BigDecimal.valueOf(d).setScale(scale).*(bd)
}
// multiply(double,bd,30) => 0.4444444444444444000000000000000000
I expected to get 0.444444444444444444444444444444 (30 times 4 after the point)
What is wrong with my method?
Your bd isn't a BigDecimal, it's a Double:
scala> val bd = 0.111111111111111111111111111111
val bd: Double = 0.1111111111111111
It gets implicitly converted to a BigDecimal (after losing precision from Double) when you call multiply.
To create the BigDecimal, you seek, it's probably best to parse a string representation:
val bd = BigDecimal("0.111111111111111111111111111111")
// bd.scale is 30
It's also probably a good idea to explicitly set the scale again in multiply after the multiplication, as it's possible for multiplying two numbers, even with the same scale, to have greater scale than either number.
def multiply(d: Double, bd: BigDecimal, scale:Int): BigDecimal =
(BigDecimal.valueOf(d).setScale(scale) * bd).setScale(scale)
Scala's BigDecimal is similar to Java's BigDecimal.
When you multiply two BigDecimals together (using the * method on the left one), you get a new BigDecimal whose scale is the sum of the scale of its operands (inputs).
The variable bd is not a BigDecimal, so its name is misleading. It is actually a double. In order to instantiate a BigDecimal, you should use a constructor, for example: BigDecimal("0.111111111111111111111111111111").
val bd = BigDecimal("0.111111111111111111111111111111")
val double = 4.0
// There is no need to call `setScale` on `d` due to the first point noted above. Set it after multiplying:
def multiply(d : Double, bd : BigDecimal, scale: Int) =
(BigDecimal.valueOf(d) * bd).setScale(scale)
val result = multiply(double, bd, 30)
println(result)
println(result.scale)
Result:
0.444444444444444444444444444444
30

Multiply a BigDecimal with an Integer

I want to multiply a financial amount with a quantity. I know Scala uses Java's BigDecimal under the hood but the syntax doesn't seem to be the same.
val price = BigDecimal("0.01") // £0.01
val qty = 10
I tried to do this
BigDecimal(price).*(BigDecimal(qty))
But it's a compile error. If I look at the Java SO posts you can pass integer into BigDecimal and then multiply it like this
BigDecimal(price).multiply(BigDecimal(qty))
So how do you do this in Scala? And are there any dangers in losing precision by multiplying a decimal and integer like this? I will need sum a lot of these together as well
You can actually multiply a BigDecimal with an Int using BigDecimal's multiplication operator:
def *(that: BigDecimal): BigDecimal
since the Int you will provide as its parameter will be implicitly converted to a BigDecimal based on:
implicit def int2bigDecimal(i: Int): BigDecimal
You can thus safely multiply your BigDecimal with an Int as if it was a BigDecimal and receive a BigDecimal with no loss in precision:
val price = BigDecimal("0.01")
// scala.math.BigDecimal = 0.01
val qty = 10
// Int = 10
price * qty // same as BigDecimal("0.01").*(10)
// scala.math.BigDecimal = 0.10
You can do this:
val a = 10
val b = BigDecimal(0.1000000000001)
a * b
res0: scala.math.BigDecimal = 1.0000000000010
As you can see you don´t lose precision
The problem is actually this:
BigDecimal(price)
price is already a BigDecimal so the compiler does't know what to do! If you fix this, the first version works. The second version fails because there is no multiply method on BigDecimal.
However, as others have pointed out, the simple solution is just
price*qty

Ways of aliasing in scala?

I am trying to figure out if Scala programming language has a way of Aliasing(presence of two or more distinct referencing methods for the same memory location).
I can see example of type aliasing such as "x: (Int, String) = (1,one)". So x has two different types but do they share same memory?
I would greatly appreciate if anyone could give more explanation.
If you want one "variable" to track another, you could do something like this.
scala> var x = 5 // create a variable
x: Int = 5
scala> def y = x // keep track of x
y: Int
scala> x = 9 // change x
x: Int = 9
scala> y // yep, y changes too
res1: Int = 9
This isn't a true alias. You can't modify y and see the change in x. A def is simply re-evaluated every time it is invoked, so every time you query y, it re-examines x for the current value.
Note that this type of thing is not considered good Scala practice. In Functional Programming you want to avoid data structures that maintain state, i.e. don't use a var if you don't have to, and good Scala programmers almost never have to.

Is there a way to avoid to convert number types in Scala? Should I use Numeric, Integral?

I would like to not to mind about type of numbers.
All numbers could be treated as Double,
but I would like to know the better scalaish way to use numbers just as numbers.
This is just one example, suppose I have the following:
val n = 5
val l = List(1,2,3,4,5) grouped (n / 2d).ceil.toInt
Is there a way to do just (exactly):
val l = List(1,2,3,4,5) grouped (n / 2).ceil
with no compilation error due to the mismatched type of 'grouped' parameter?
EDIT
The n / 2 in grouped (n / 2).ceil part could be, in another example, the non integer result of a function f:
grouped f.ceil
It still needs type conversion, or in all situations there is a trick or design pattern to avoid it?
val l = List(1,2,3,4,5) grouped((n + 1) / 2)
You could check out the numeric library Spire, I believe it has what you are looking for, namely, the ability to treat numbers as numbers whether they are int/double/float/etc.
There is a way to do it. You can define an implicit conversion like this:
implicit def double2Int(d: Double): Int = d.toInt
Once that's in scope, it will convert any Double automatically to Int. However, doing so is not recommended, as you lose type safety.

reduce list of integers/range of integers in scala

Total newbie question here...Today while trying to calculate sum of a list of integers(actually BitSet), I ran into overflow scenarios and noticed that the return type of(sum/product) is Int. Are there any methods in Range/List to sum up or say multiply all values to Long?
val x = 1 to Integer.MaxValue
println(x.sum) //prints -1453759936
thanks
Convert the elements to Long (or BigInt should that go that far) while summing:
x.view.map(_.toLong).sum
You can also go back to fold
x.foldLeft(0L)(_ + _)
(Note: should you sum over a range, maybe it would be better do a little math, but I understand that is not what you did in fact)
Compare:
>> val x = 1 to Int.MaxValue
x: scala.collection.immutable.Range.Inclusive with scala.collection.immutable.Range.ByOne = Range(...)
With:
>> val x = 1L to Int.MaxValue
x: scala.collection.immutable.NumericRange.Inclusive[Long] = NumericRange(...)
Note that the first uses Int.to, and the latter used Long.to (where Int.MaxValue is up-converted automatically). Of course, the sum of a consecutive integer sequence has a very nice discrete formula :)
Happy coding.
This isn't very efficient, but the easiest way:
val x = 1L to Int.MaxValue
println(x.sum) //prints 2305843008139952128
If you need x to contain Ints rather than Longs, you can do
val x = 1 to Int.MaxValue
println(x.foldLeft(0L)(_+_))
Range.Long(1, Int.MaxValue, 1).sum