0

I saw this function on Percentile calculation, so I copied it and pasted it into the compiler, and it gives me an OutOfRange exception at

        else
        {
            int k = (int)n;
            double d = n - k;
            return sequence[k - 1] + d * (sequence[k] - sequence[k - 1]);//EXCEPTION
        }

What could be the source of the problem, and how do I solve it?

Function:

 public double Percentile(double[] sequence, double excelPercentile)
 {
    Array.Sort(sequence);
    int N = sequence.Length;
    double n = (N - 1) * excelPercentile + 1;
    // Another method: double n = (N + 1) * excelPercentile;
    if (n == 1d) return sequence[0];
    else if (n == N) return sequence[N - 1];
    else
    {
         int k = (int)n;
         double d = n - k;
         return sequence[k - 1] + d * (sequence[k] - sequence[k - 1]);
    }
}
Community
  • 1
  • 1
lost_in_the_source
  • 10,998
  • 9
  • 46
  • 75

2 Answers2

2

The issue is that k is a number larger than the number of items in the array.

TGH
  • 38,769
  • 12
  • 102
  • 135
  • You have to ensure that you don't pass in a value for k that is too large. – TGH Nov 07 '13 at 02:30
  • 1
    Your quoted code has the following comment: `Excel uses a percentile value between 0 and 1`. Chances are that you are using a value for `excelPercentile` that is > 1. e.g. for the 5th percentile you should be using 0.05 instead of 5. – Ben T Nov 07 '13 at 03:27
1

As was mentioned, the function is designed to work with values between 0 and 1. Restricting the input should correct the problem.

 public double Percentile(double[] sequence, double excelPercentile)
 {
    //if(excelPercentile > 1)
        //excelPercentile = 1;
    //else if(excelPercentile < 0)
        //excelPercentile = 0;
    //Depending on how you validate the input you can assume that it's a whole number percentage.  Then you only need to check for the number to be between 0 and 100
    if(excelPercentile > 100)
       excelPercentile = 100;
    else if(excelPercentile < 0)
       excelPercentile = 0;
    excelPercentile /= 100;
    Array.Sort(sequence);
    int N = sequence.Length;
    double n = (N - 1) * excelPercentile + 1;
    // Another method: double n = (N + 1) * excelPercentile;
    if (n == 1d) return sequence[0];
    else if (n == N) return sequence[N - 1];
    else
    {
         int k = (int)n;
         double d = n - k;
         return sequence[k - 1] + d * (sequence[k] - sequence[k - 1]);
    }
}
tinstaafl
  • 6,908
  • 2
  • 15
  • 22
  • Is it OK to change the input, for example if I enter "50", the code will make the input into ".5"(a while loop that keeps dividing the input by 10 until it is less than 1) and THEN using it throughout the rest of the code? – lost_in_the_source Nov 08 '13 at 01:37
  • 1
    I added code to allow the excelPercentile to be a whole number rather than a fraction – tinstaafl Nov 08 '13 at 02:24