将百分比转换为最近的分数

我们有一个数据密集型系统。 它存储原始数据,然后根据正确响应数/总试验数计算百分比。

最近我们有客户想要将旧数据导入我们的系统。

我需要一种方法将百分比转换为最接近的分数。

例子。

  1. 33%需要给我2/6。 即使1/3是.33333333
  2. 67%需要给我4/6。 即使4/6是.6666667

我意识到我可以将其计算为67/100,但这意味着当6个就足够时我必须向系统添加100个数据点。

有没有人有任何想法?

EDIT Denominator可以是任何东西。 他们给了我一个原始的,圆润的百分比,我试图尽可能接近RAW数据

您的要求是矛盾的:一方面,您希望“将百分比转换为最接近的分数”(*),但另一方面,您需要具有小(可)数字的分数。 你需要找到一些妥协的时候/如何降低精度以支持更小的数字。 你现在的问题是无法解决的。

(*)对于任何给定(整数)百分比n,最接近的分数f是n / 100。 根据定义。

我试图通过使用连续分数来满足您的要求。 通过将深度限制为三,我得到了一个合理的近似值。

我没能在合理的时间内提出迭代(或递归)方法。 不过我已经清理了一下。 (我知道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 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(1, a_r); else if (Math.Abs(b_r / (a_t * b_r + 1.0) - value) <= tolerance) return new KeyValuePair(b_r, a_t * b_r + 1); else return new KeyValuePair(c * b_t + 1, c * a_t * b_t + a_t + c); } } 

是否必须返回2/6而不是1/3? 如果它总是在6日,那么

 Math.Round((33 * 6)/100) = 2 

在这里回答我自己的问题。 这会有用吗?

  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。