1. ホーム
  2. c#

[解決済み] 3つの長整数の平均値

2022-12-07 16:45:03

質問

非常に大きな符号付き整数を3つ持っています。

long x = long.MaxValue;
long y = long.MaxValue - 1;
long z = long.MaxValue - 2;

その切り捨て平均を計算したい。期待される平均値は long.MaxValue - 1 であるが、これは 9223372036854775806 .

として計算することは不可能である。

long avg = (x + y + z) / 3; // 3074457345618258600

注:2つの数値の平均に関するすべての質問を読みましたが、そのテクニックが3つの数値の平均にどのように適用できるかがわかりません。

の使用で非常に簡単になります。 BigInteger を使えば非常に簡単なのですが、使えないと仮定しましょう。

BigInteger bx = new BigInteger(x);
BigInteger by = new BigInteger(y);
BigInteger bz = new BigInteger(z);
BigInteger bavg = (bx + by + bz) / 3; // 9223372036854775806

に変換すると double に変換すると、当然ながら精度が落ちます。

double dx = x;
double dy = y;
double dz = z;
double davg = (dx + dy + dz) / 3; // 9223372036854780000

に変換すると decimal に変換すると、動作しますが、使えないとします。

decimal mx = x;
decimal my = y;
decimal mz = z;
decimal mavg = (mx + my + mz) / 3; // 9223372036854775806

質問です。 のみを用いて、3つの非常に大きな整数の切断平均を計算する方法はありますか? long 型の使用だけで3つの非常に大きな整数の切り捨て平均を計算する方法はありますか?その質問をC#特有のものと考えないでください。ただ、私がC#でサンプルを提供するのは簡単です。

どのように解決するのですか?

このコードは動作しますが、それほどきれいではありません。

これはまず3つの値をすべて割り算し(値を床にしているので、余りを「失う」)、それから余りを割り算します。

long n = x / 3
         + y / 3
         + z / 3
         + ( x % 3
             + y % 3
             + z % 3
           ) / 3

上記のサンプルは、1つ以上の負の値を持つ場合、必ずしも正しく動作しないことに注意してください。

Ulugbekと話し合ったように、以下コメント数が爆発的に増えているため、正負両方の値に対する現在のBESTな解決策を紹介します。

の回答やコメントに感謝します。 Ulugbek Umirov , ジェームス S , ケビンZ , マーク・ヴァン・リューウェン , gnasher729 というのが現在の解決策です。

static long CalculateAverage(long x, long y, long z)
{
    return (x % 3 + y % 3 + z % 3 + 6) / 3 - 2
            + x / 3 + y / 3 + z / 3;
}

static long CalculateAverage(params long[] arr)
{
    int count = arr.Length;
    return (arr.Sum(n => n % count) + count * (count - 1)) / count - (count - 1)
           + arr.Sum(n => n / count);
}