转换为分数英寸

时间:2016-08-11 08:34:46

标签: c# math fractions

我需要使用以下格式将double值(厘米)转换为分数值:3 1/64(英寸)。在阅读了很多关于这个并找到转换成分数的算法之后,我认为它们对我所需要的不好,因为我的分数应该是以下格式:?/ 2,?/ 4,?/ 8,?/ 16, ?/ 32,?/ 64。我见过这样的转换表:table。我认为我最好的解决方案是创建一个包含表格中所有值的键值列表,并为每个数字找到列表中的最佳近似值。

例如:3.21厘米。 = 1.26378 in = 1 in + 0.26378。所以,根据表格链接,0.26378 = 17/64。最终结果应为1 17/64英寸。

所以我的问题是:

  1. 最好有一个包含表中值的列表,并找到最接近的值以给出分数,或者最好为此创建算法?

  2. 如果可以创建包含值的列表,我怎样才能在列表中找到给定数字的最接近值?

3 个答案:

答案 0 :(得分:3)

我建议使用简单的数学而不是表格

private static string ToFraction64(double value) {
  // denominator is fixed
  int denominator = 64;
  // integer part, can be signed: 1, 0, -3,...
  int integer = (int) value;
  // numerator: always unsigned (the sign belongs to the integer part)
  // + 0.5 - rounding, nearest one: 37.9 / 64 -> 38 / 64; 38.01 / 64 -> 38 / 64
  int numerator = (int) ((Math.Abs(value) - Math.Abs(integer)) * denominator + 0.5);

  // some fractions, e.g. 24 / 64 can be simplified:
  // both numerator and denominator can be divided by the same number
  // since 64 = 2 ** 6 we can try 2 powers only 
  // 24/64 -> 12/32 -> 6/16 -> 3/8
  // In general case (arbitrary denominator) use gcd (Greatest Common Divisor):
  //   double factor = gcd(denominator, numerator);
  //   denominator /= factor;
  //   numerator /= factor;
  while ((numerator % 2 == 0) && (denominator % 2 == 0)) {
    numerator /= 2;
    denominator /= 2;
  }

  // The longest part is formatting out

  // if we have an actual, not degenerated fraction (not, say, 4 0/1)
  if (denominator > 1)
    if (integer != 0) // all three: integer + numerator + denominator
      return string.Format("{0} {1}/{2}", integer, numerator, denominator);
    else if (value < 0) // negative numerator/denominator, e.g. -1/4
      return string.Format("-{0}/{1}", numerator, denominator);
    else // positive numerator/denominator, e.g. 3/8
      return string.Format("{0}/{1}", numerator, denominator);
  else 
    return integer.ToString(); // just an integer value, e.g. 0, -3, 12...  
}

测试

const double cmInInch = 2.54;

// 1 17/64
Console.Write(ToFraction64(3.21 / cmInInch));
// -1 17/64
Console.Write(ToFraction64(-1.26378));
// 3 1/4
Console.Write(ToFraction64(3.25001));
// 3 1/4
Console.Write(ToFraction64(3.24997));
// 5
Console.Write(ToFraction64(5.000001));
// -1/8
Console.Write(ToFraction64(-0.129));
// 1/8
Console.Write(ToFraction64(0.129));

答案 1 :(得分:0)

采用德米特里·拜琴科(Dmitry Bychenko)的代码,如果分数等于1,则需要添加大小写“ else if(分母==分子)”;如果值是正数,则添加1;如果值是负,则删除1(如果分母) / numerator = 64/64)

    private static string ToFraction64(double value)
    {
        // denominator is fixed
        int denominator = 64;
        // integer part, can be signed: 1, 0, -3,...
        int integer = (int)value;
        // numerator: always unsigned (the sign belongs to the integer part)
        // + 0.5 - rounding, nearest one: 37.9 / 64 -> 38 / 64; 38.01 / 64 -> 38 / 64
        int numerator = (int)((Math.Abs(value) - Math.Abs(integer)) * denominator + 0.5);

        // some fractions, e.g. 24 / 64 can be simplified:
        // both numerator and denominator can be divided by the same number
        // since 64 = 2 ** 6 we can try 2 powers only 
        // 24/64 -> 12/32 -> 6/16 -> 3/8
        // In general case (arbitrary denominator) use gcd (Greatest Common Divisor):
        //   double factor = gcd(denominator, numerator);
        //   denominator /= factor;
        //   numerator /= factor;
        while ((numerator % 2 == 0) && (denominator % 2 == 0))
        {
            numerator /= 2;
            denominator /= 2;
        }

        // The longest part is formatting out

        // if we have an actual, not degenerated fraction (not, say, 4 0/1)
        if (denominator > 1)
            if (integer != 0) // all three: integer + numerator + denominator
                return string.Format("{0} {1}/{2}", integer, numerator, denominator);
            else if (value < 0) // negative numerator/denominator, e.g. -1/4
                return string.Format("-{0}/{1}", numerator, denominator);
            else // positive numerator/denominator, e.g. 3/8
                return string.Format("{0}/{1}", numerator, denominator);
        //if fraction equals to 1 we add 1 if the value is positive or remove 1 if the value is negative (ex denominator/numerator = 64/64)
        else if (denominator == numerator)
        {
            if (value < 0) // negative numerator/denominator, e.g. -1/4               
                integer--;
            else // positive numerator/denominator, e.g. 3/8               
                integer++;
            return integer.ToString();
        }
        else
            return integer.ToString(); // just an integer value, e.g. 0, -3, 12...  
    }

答案 2 :(得分:0)

我的功能更简单更简单.. 它从十进制值返回一个包含三个整数 {Inches, Numerator, Denominator} 的数组,fracBase 参数表示精度为 16、32、64、128 ... .

public static int[] GetImpFractions(decimal value, int fracBase = 32)
{
    int[] result = { 0, 0, 0 };

    result[0] = (int)Math.Truncate(value);
    decimal num = (value - (decimal)result[0]);
    num *= fracBase;
    decimal denom = fracBase;
    if (num > 0)
    {
        while (num % 2 == 0) 
        {
            num /= 2;
            denom /= 2;
        }
        if (num == 1 && denom == 1)
        {
            result[0] += 1;
            num = 0; 
            denom = 0;
        }
        result[1] = (int)Math.Truncate(num);
        result[2] = (int)Math.Truncate(denom);
    }

    return result;
}