7

私たちは非常にデータ集約的なシステムを持っています。生データを保存し、正解数/総試行回数に基づいてパーセンテージを計算します。

最近、古いデータを当社のシステムにインポートしたいお客様がいらっしゃいました。

パーセンテージを最も近い分数に変換する方法が必要です。

例。

  1. 33% は私に 2/6 を与える必要があります。でも 1/3 は .33333333
  2. 67% は私に 4/6 を与える必要があります。EVEN でも 4/6 は .6666667 です

67/100 と計算するだけでよいことはわかっていますが、6 で十分な場合、システムに 100 のデータ ポイントを追加する必要があります。

誰にもアイデアはありますか?

編集 分母は何でもかまいません。彼らは私に未加工の丸められたパーセンテージを与えており、私はRAWデータでそれにできるだけ近づけようとしています.

4

4 に答える 4

4

あなたの要件は矛盾しています: 一方では、「パーセンテージを最も近い分数に変換」(*) したいのですが、他方では、小さい (est) 数値の分数が必要です。小さい数値を優先して精度をいつ/どのように下げるかについて、妥協点を見つける必要があります。あなたの問題はそのままでは解決できません。

(*) 任意の (整数) パーセンテージ n に対する最も近い分数 f は n/100 です。定義ごと。

于 2013-01-14T15:25:34.250 に答える
1

連分数を使用して、お客様の要件を満たすように努めました。深さを3に制限することで、妥当な近似値が得られました。

妥当な時間内に反復(または再帰)アプローチを思い付くことができませんでした。それにもかかわらず、私はそれを少しきれいにしました。(私は3文字の変数名が良くないことを知っていますが、それらの良い名前を考えることはできません:-/)

このコードは、指定された許容範囲内で見つけることができる最良の有理近似を提供します。結果として得られる分数は減少し、同じまたはより低い分母を持つすべての分数の中で最良の近似になります。

public partial class Form1 : Form
{
    Random rand = new Random();

    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        for (int i = 0; i < 10; i++)
        {
            double value = rand.NextDouble();
            var fraction = getFraction(value);
            var numerator = fraction.Key;
            var denominator = fraction.Value;

            System.Console.WriteLine(string.Format("Value {0:0.0000} approximated by {1}/{2} = {3:0.0000}", value, numerator, denominator, (double)numerator / denominator));
        }
        /*
            Output:
            Value 0,4691 approximated by 8/17 = 0,4706
            Value 0,0740 approximated by 1/14 = 0,0714
            Value 0,7690 approximated by 3/4 = 0,7500
            Value 0,7450 approximated by 3/4 = 0,7500
            Value 0,3748 approximated by 3/8 = 0,3750
            Value 0,7324 approximated by 3/4 = 0,7500
            Value 0,5975 approximated by 3/5 = 0,6000
            Value 0,7544 approximated by 3/4 = 0,7500
            Value 0,7212 approximated by 5/7 = 0,7143
            Value 0,0469 approximated by 1/21 = 0,0476
            Value 0,2755 approximated by 2/7 = 0,2857
            Value 0,8763 approximated by 7/8 = 0,8750
            Value 0,8255 approximated by 5/6 = 0,8333
            Value 0,6170 approximated by 3/5 = 0,6000
            Value 0,3692 approximated by 3/8 = 0,3750
            Value 0,8057 approximated by 4/5 = 0,8000
            Value 0,3928 approximated by 2/5 = 0,4000
            Value 0,0235 approximated by 1/43 = 0,0233
            Value 0,8528 approximated by 6/7 = 0,8571
            Value 0,4536 approximated by 5/11 = 0,4545
         */
    }

    private KeyValuePair<int, int> getFraction(double value, double tolerance = 0.02)
    {
        double f0 = 1 / value;
        double f1 = 1 / (f0 - Math.Truncate(f0));

        int a_t = (int)Math.Truncate(f0);
        int a_r = (int)Math.Round(f0);
        int b_t = (int)Math.Truncate(f1);
        int b_r = (int) Math.Round(f1);
        int c = (int)Math.Round(1 / (f1 - Math.Truncate(f1)));

        if (Math.Abs(1.0 / a_r - value) <= tolerance)
            return new KeyValuePair<int, int>(1, a_r);
        else if (Math.Abs(b_r / (a_t * b_r + 1.0) - value) <= tolerance)
            return new KeyValuePair<int, int>(b_r, a_t * b_r + 1);
        else
            return new KeyValuePair<int, int>(c * b_t + 1, c * a_t * b_t + a_t + c);
    }
}
于 2013-01-14T16:44:26.443 に答える
0

1/3 ではなく 2/6 を返す必要がありますか? 常に 6 度の場合、

Math.Round((33 * 6)/100) = 2
于 2013-01-14T15:06:03.737 に答える
0

ここで自分の質問に答えます。これは機能しますか?

    public static Fraction Convert(decimal value) {
    for (decimal numerator = 1; numerator <= 10; numerator++) {
        for (decimal denomenator = 1; denomenator < 10; denomenator++) {
            var result = numerator / denomenator;
            if (Math.Abs(value - result) < .01m)
                return new Fraction() { Numerator = numerator, Denomenator = denomenator };
        }
    }

    throw new Exception();
}

これにより、分母が 10 未満に保たれます。

于 2013-01-14T15:14:53.440 に答える