Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Percentile calculator

I have been trying to create a small method to calculate given percentile from a seq. It works.. almost. Problem is I don't know why is doesn't work. I was hoping one of your 'a bit smarter' people than me could help me with it.

What I hope the result would be is that it would return the item from the seq that n prosent of the seq is smaller than equal than returned value.

def percentile[Int](p: Int)(seq: Seq[Int]) = {
  require(0 <= p && p <= 100)                      // some value requirements
  require(!seq.isEmpty)                            // more value requirements
  val sorted = seq.sorted
  val k = math.ceil((seq.length - 1) * (p / 100)).toInt
  return sorted(k)
}

So for example if I have

val v = Vector(7, 34, 39, 18, 16, 17, 21, 36, 17, 2, 4, 39, 4, 19, 2, 12, 35, 13, 40, 37)

and I call my function percentile(11)(v) return value is 2. However, 10% of the vector are smaller or equal than 2, not 11% like I am calling. percentile(11)(v) should return 4.

like image 912
Selena Hill Avatar asked Apr 07 '16 14:04

Selena Hill


2 Answers

your error is in this row:

 val k = math.ceil((seq.length - 1) * (p / 100)).toInt

and particularly here: p / 100. Being p an Int <= 100 and >= 0, p/100 will always be equal to 0 or 1 (if p == 100). If you want a floating point result, you have to widen one of the two values to double: p/100.0

 val k = math.ceil((seq.length - 1) * (p / 100.0)).toInt

On a side note: you don't need the [Int] type parameter

like image 141
Giovanni Caporaletti Avatar answered Nov 15 '22 03:11

Giovanni Caporaletti


The problem is with the part p / 100 in

val k = math.ceil((seq.length - 1) * (p / 100)).toInt

Since p is of type Int and 100 is also an Int, the division is an integer division that returns an Int. If either p or 100 is a Double, the result will be a Double.

The easiest fix would be to change that part in p / 100.0.

like image 36
Arjan Avatar answered Nov 15 '22 03:11

Arjan