web-dev-qa-db-ja.com

長い配列からパーセンタイルを計算しますか?

ミリ秒単位のレイテンシの長い配列がある場合、それらからパーセンタイルを計算します。動作する方法を以下に取得しましたが、これが正確な結果を与えるかどうかをどのように確認できるかわかりませんか?

  public static long[] percentiles(long[] latencies, double... percentiles) {
    Arrays.sort(latencies, 0, latencies.length);
    long[] values = new long[percentiles.length];
    for (int i = 0; i < percentiles.length; i++) {
      int index = (int) (percentiles[i] * latencies.length);
      values[i] = latencies[index];
    }
    return values;
  }

latencies配列から50、95、99、99.9パーセンタイルを取得したいと思います。

long[] percs = percentiles(latencies, 0.5, 0.95, 0.99, 0.999);

これは、レイテンシの長い配列を想定してパーセンタイルを取得する正しい方法ですか?私はJava 7.を使用しています。

8
user5447339

これはあなたが探しているものです:

class Program
{
    static void Main(string[] args)
    {
        List<long> latencies = new List<long>() { 3, 6, 7, 8, 8, 9, 10, 13, 15, 16, 20 };

        Console.WriteLine(Percentile(latencies,25));
        Console.WriteLine(Percentile(latencies, 50));
        Console.WriteLine(Percentile(latencies, 75));
        Console.WriteLine(Percentile(latencies, 100));

        Console.ReadLine();
    }

    public static long Percentile(List<long> latencies, double Percentile)
    {
        latencies.Sort();
        int Index = (int)Math.Ceiling(((double)Percentile / (double)100) * (double)latencies.Count);
        return latencies[Index-1];
    }
}

enter image description here

9
user7358693

Wikipedia によると、パーセンタイルの標準的な定義はありません。ただし、可能な定義はいくつかあります。投稿したコードは最近傍ランク法に最も近いようですが、まったく同じではありません。

彼らが与える式は

n = ceiling((P / 100) x N)

ここで、Nはリストの長さ、Pはパーセンタイル、nは序数ランクです。あなたはすでに100による除算を行っています。彼らが与える例を見ると、「序数ランク」がリスト内のインデックスであることは明らかですが、それは1相対です。したがって、Java配列にインデックスを取得するには、1を減算する必要があります。したがって、正しい数式は次のようになります。

n = ceiling(percentile * N) - 1

コードで変数を使用すると、Javaと同等になります

(int) Math.ceil(percentiles[i] * latencies.length) - 1

これはあなたが書いたコードではありません。 doubleintにキャストすると、結果は0に丸められます。つまり、「floor」関数と同等です。だからあなたのコードは計算します

floor(percentiles[i] * latencies.length)

percentiles[i] * latencies.lengthは整数ではなく、結果はどちらの方法でも同じです。ただし、整数の場合、「floor」と「ceiling」が同じ値になると、結果が異なります。

ウィキペディアの例は、リストが{15、20、35、40、50}の場合に40パーセンタイルを計算することです。彼らの答えは、0.40 * 5 = 2.0、およびceiling(2.0)= 2.0であるため、リストの2番目の項目、つまり20を見つけることです。

ただし、コード:

int index = (int) (percentiles[i] * latencies.length);

indexは2になります。これは、2番目のアイテムではなく、リストの3番目のアイテムを取得するため、望ましいものではありません。

したがって、ウィキペディアの定義と一致させるには、インデックスの計算を少し変更する必要があります。 (一方で、誰かがやって来て、あなたの計算が正しく、ウィキペディアが間違っていると言っても私は驚かないでしょう。わかります...)

1
ajb