Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/264.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 小数简化为分数的算法_C#_.net_Algorithm_Math - Fatal编程技术网

C# 小数简化为分数的算法

C# 小数简化为分数的算法,c#,.net,algorithm,math,C#,.net,Algorithm,Math,我试着写一个算法,把一个小数简化成一个小数,然后意识到它并不太简单。令人惊讶的是,我上网查看了所有代码,发现它们要么太长,要么在某些情况下不起作用。更令人恼火的是,它们不适用于循环小数。然而,我想知道这里是否会有一位数学家/程序员,他了解将小数简化为小数所涉及的所有过程。有人吗?我知道你说你在网上搜索过,但是如果你错过了下面的文章,可能会有所帮助。它包括一个Pascal的代码示例 * 或者,作为其标准库的一部分,Ruby具有处理有理数的代码。它可以从浮动转换为理性,反之亦然。我相信您也可以查看代

我试着写一个算法,把一个小数简化成一个小数,然后意识到它并不太简单。令人惊讶的是,我上网查看了所有代码,发现它们要么太长,要么在某些情况下不起作用。更令人恼火的是,它们不适用于循环小数。然而,我想知道这里是否会有一位数学家/程序员,他了解将小数简化为小数所涉及的所有过程。有人吗?

我知道你说你在网上搜索过,但是如果你错过了下面的文章,可能会有所帮助。它包括一个Pascal的代码示例

*

或者,作为其标准库的一部分,Ruby具有处理有理数的代码。它可以从浮动转换为理性,反之亦然。我相信您也可以查看代码。可以找到文档。我知道你没有使用Ruby,但是看看算法可能会有所帮助

此外,如果使用,您可以从C#调用Ruby代码(甚至在C#代码文件中编写Ruby代码),它运行在.net framework之上


*更新到一个新的链接,因为原来的URL被破坏了()

我知道你说你在网上搜索过,但是如果你错过了下面的文章,可能会有所帮助。它包括一个Pascal的代码示例

*

或者,作为其标准库的一部分,Ruby具有处理有理数的代码。它可以从浮动转换为理性,反之亦然。我相信您也可以查看代码。可以找到文档。我知道你没有使用Ruby,但是看看算法可能会有所帮助

此外,如果使用,您可以从C#调用Ruby代码(甚至在C#代码文件中编写Ruby代码),它运行在.net framework之上


*更新为新链接,因为原始URL已被破坏()

您不能在.net中表示循环小数,因此我将忽略您问题的这一部分

只能表示有限且相对较少的位数

有一个非常简单的算法:

   Public Shared Sub float_to_fraction(x As Decimal, ByRef Numerator As Long, ByRef Denom As Long, Optional ErrMargin As Decimal = 0.001)
    Dim n As Long = Int(Math.Floor(x))
    x -= n

    If x < ErrMargin Then
        Numerator = n
        Denom = 1
        Return
    ElseIf x >= 1 - ErrMargin Then
        Numerator = n + 1
        Denom = 1
        Return
    End If

    ' The lower fraction is 0/1
    Dim lower_n As Integer = 0
    Dim lower_d As Integer = 1
    ' The upper fraction is 1/1
    Dim upper_n As Integer = 1
    Dim upper_d As Integer = 1

    Dim middle_n, middle_d As Decimal
    While True
        ' The middle fraction is (lower_n + upper_n) / (lower_d + upper_d)
        middle_n = lower_n + upper_n
        middle_d = lower_d + upper_d
        ' If x + error < middle
        If middle_d * (x + ErrMargin) < middle_n Then
            ' middle is our new upper
            upper_n = middle_n
            upper_d = middle_d
            ' Else If middle < x - error
        ElseIf middle_n < (x - ErrMargin) * middle_d Then
            ' middle is our new lower
            lower_n = middle_n
            lower_d = middle_d
            ' Else middle is our best fraction
        Else
            Numerator = n * middle_d + middle_n
            Denom = middle_d
            Return
        End If
    End While
End Sub
  • 取十进制
    x
  • 计算小数点后的位数;称之为
    n
  • 创建一个分数
    (10^n*x)/10^n
  • 从分子和分母中去掉公因子
所以如果你有0.44,你会数到小数点的2位-n=2,然后写下

  • (0.44*10^2)/10^2
  • =
    44/100
  • 因子分解(去掉公因子4)得到
    11/25

    • 您不能在.net中表示循环小数,因此我将忽略您问题的这一部分

      只能表示有限且相对较少的位数

      有一个非常简单的算法:

         Public Shared Sub float_to_fraction(x As Decimal, ByRef Numerator As Long, ByRef Denom As Long, Optional ErrMargin As Decimal = 0.001)
          Dim n As Long = Int(Math.Floor(x))
          x -= n
      
          If x < ErrMargin Then
              Numerator = n
              Denom = 1
              Return
          ElseIf x >= 1 - ErrMargin Then
              Numerator = n + 1
              Denom = 1
              Return
          End If
      
          ' The lower fraction is 0/1
          Dim lower_n As Integer = 0
          Dim lower_d As Integer = 1
          ' The upper fraction is 1/1
          Dim upper_n As Integer = 1
          Dim upper_d As Integer = 1
      
          Dim middle_n, middle_d As Decimal
          While True
              ' The middle fraction is (lower_n + upper_n) / (lower_d + upper_d)
              middle_n = lower_n + upper_n
              middle_d = lower_d + upper_d
              ' If x + error < middle
              If middle_d * (x + ErrMargin) < middle_n Then
                  ' middle is our new upper
                  upper_n = middle_n
                  upper_d = middle_d
                  ' Else If middle < x - error
              ElseIf middle_n < (x - ErrMargin) * middle_d Then
                  ' middle is our new lower
                  lower_n = middle_n
                  lower_d = middle_d
                  ' Else middle is our best fraction
              Else
                  Numerator = n * middle_d + middle_n
                  Denom = middle_d
                  Return
              End If
          End While
      End Sub
      
      • 取十进制
        x
      • 计算小数点后的位数;称之为
        n
      • 创建一个分数
        (10^n*x)/10^n
      • 从分子和分母中去掉公因子
      所以如果你有0.44,你会数到小数点的2位-n=2,然后写下

      • (0.44*10^2)/10^2
      • =
        44/100
      • 因子分解(去掉公因子4)得到
        11/25

      我找到了Matt引用的同一篇论文,我花了一秒钟时间用Python实现了它。也许在代码中看到相同的想法会让它更清晰。诚然,您要求用C#给出答案,我将用Python给您,但这是一个相当简单的程序,我相信它很容易翻译。参数是
      num
      (要转换为有理数的十进制数)和
      epsilon
      num
      和计算有理数之间允许的最大差值)。一些快速测试运行发现,当
      epsilon
      大约为1e-4时,通常只需要两到三次迭代就可以收敛

      def dec2frac(num,epsilon,max_iter=20): d=[0,1]+([0]*最大值) z=num n=1 t=1 而num和tε: t+=1 z=1/(z-int(z)) d[t]=d[t-1]*int(z)+d[t-2] #int(x+0.5)等于四舍五入x。 n=int(num*d[t]+0.5) 返回n,d[t] 编辑:我刚刚注意到你的说明,希望他们使用循环小数。我不知道有哪种语言的语法支持循环小数,因此我不确定如何处理它们,但通过此方法运行0.66666和0.166666会返回正确的结果(分别为2/3和1/6)


      另一个编辑(我不认为这会如此有趣!):如果你想了解更多关于这个算法背后的理论,

      我找到了Matt引用的同一篇论文,我花了一秒钟时间用Python实现了它。也许在代码中看到相同的想法会让它更清晰。诚然,您要求用C#给出答案,我将用Python给您,但这是一个相当简单的程序,我相信它很容易翻译。参数是
      num
      (要转换为有理数的十进制数)和
      epsilon
      num
      和计算有理数之间允许的最大差值)。一些快速测试运行发现,当
      epsilon
      大约为1e-4时,通常只需要两到三次迭代就可以收敛

      def dec2frac(num,epsilon,max_iter=20): d=[0,1]+([0]*最大值) z=num n=1 t=1 而num和tε: t+=1 z=1/(z-int(z)) d[t]=d[t-1]*int(z)+d[t-2] #int(x+0.5)等于四舍五入x。 n=int(num*d[t]+0.5) 返回n,d[t] 编辑:我刚刚注意到你的说明,希望他们使用循环小数。我不知道
      static readonly Regex FractionalExpression = new Regex(@"^(?<sign>[-])?(?<numerator>\d+)(/(?<denominator>\d+))?$");
      public static decimal? FractionToDecimal(string fraction)
      {
          var match = FractionalExpression.Match(fraction);
          if (match.Success)
          {
              // var sign = Int32.Parse(match.Groups["sign"].Value + "1");
              var numerator = Int32.Parse(match.Groups["sign"].Value + match.Groups["numerator"].Value);
              int denominator;
              if (Int32.TryParse(match.Groups["denominator"].Value, out denominator))
                  return denominator == 0 ? (decimal?)null : (decimal)numerator / denominator;
              if (numerator == 0 || numerator == 1)
                  return numerator;
          }
          return null;
      }
      
         Public Shared Sub float_to_fraction(x As Decimal, ByRef Numerator As Long, ByRef Denom As Long, Optional ErrMargin As Decimal = 0.001)
          Dim n As Long = Int(Math.Floor(x))
          x -= n
      
          If x < ErrMargin Then
              Numerator = n
              Denom = 1
              Return
          ElseIf x >= 1 - ErrMargin Then
              Numerator = n + 1
              Denom = 1
              Return
          End If
      
          ' The lower fraction is 0/1
          Dim lower_n As Integer = 0
          Dim lower_d As Integer = 1
          ' The upper fraction is 1/1
          Dim upper_n As Integer = 1
          Dim upper_d As Integer = 1
      
          Dim middle_n, middle_d As Decimal
          While True
              ' The middle fraction is (lower_n + upper_n) / (lower_d + upper_d)
              middle_n = lower_n + upper_n
              middle_d = lower_d + upper_d
              ' If x + error < middle
              If middle_d * (x + ErrMargin) < middle_n Then
                  ' middle is our new upper
                  upper_n = middle_n
                  upper_d = middle_d
                  ' Else If middle < x - error
              ElseIf middle_n < (x - ErrMargin) * middle_d Then
                  ' middle is our new lower
                  lower_n = middle_n
                  lower_d = middle_d
                  ' Else middle is our best fraction
              Else
                  Numerator = n * middle_d + middle_n
                  Denom = middle_d
                  Return
              End If
          End While
      End Sub
      
          public static string DoubleToFraction(double num, double epsilon = 0.0001, int maxIterations = 20)
          {
              double[] d = new double[maxIterations + 2];
              d[1] = 1;
              double z = num;
              double n = 1;
              int t = 1;
      
              int wholeNumberPart = (int)num;
              double decimalNumberPart = num - Convert.ToDouble(wholeNumberPart);
      
              while (t < maxIterations && Math.Abs(n / d[t] - num) > epsilon)
              {
                  t++;
                  z = 1 / (z - (int)z);
                  d[t] = d[t - 1] * (int)z + d[t - 2];
                  n = (int)(decimalNumberPart * d[t] + 0.5);
              }
      
              return string.Format((wholeNumberPart > 0 ? wholeNumberPart.ToString() + " " : "") + "{0}/{1}",
                                   n.ToString(),
                                   d[t].ToString()
                                  );
          }
      
      //Written By Brian Dobony
      public static class Fraction
      {
          public static string ConvertDecimal(Double NumberToConvert, int DenominatorPercision = 32)
          {
              int WholeNumber = (int)NumberToConvert;
              double DecimalValue = NumberToConvert - WholeNumber;
      
              double difference = 1;
              int numerator = 1;
              int denominator = 1;
      
              // find closest value that matches percision
              // Automatically finds Fraction in simplified form
              for (int y = 2; y < DenominatorPercision + 1; y++)
              {
                      for (int x = 1; x < y; x++)
                      {
                          double tempdif = Math.Abs(DecimalValue - (double)x / (double)y);
                          if (tempdif < difference)
                          {
                              numerator = x;
                              denominator = y;
                              difference = tempdif;
                              // if exact match is found return it
                              if (difference == 0)
                              {
                                  return FractionBuilder(WholeNumber, numerator, denominator);
                              }
                          }
                      }
              }
              return FractionBuilder(WholeNumber, numerator, denominator);
          }
      
          private static string FractionBuilder(int WholeNumber, int Numerator, int Denominator)
          {
              if (WholeNumber == 0)
              {
                  return Numerator + @"/" + Denominator;
              }
              else
              {
                  return WholeNumber + " " + Numerator + @"/" + Denominator;
              }
          }
      }
      
      public Fraction RealToFraction(double value, double accuracy)
      {
          if (accuracy <= 0.0 || accuracy >= 1.0)
          {
              throw new ArgumentOutOfRangeException("accuracy", "Must be > 0 and < 1.");
          }
      
          int sign = Math.Sign(value);
      
          if (sign == -1)
          {
              value = Math.Abs(value);
          }
      
          // Accuracy is the maximum relative error; convert to absolute maxError
          double maxError = sign == 0 ? accuracy : value * accuracy;
      
          int n = (int) Math.Floor(value);
          value -= n;
      
          if (value < maxError)
          {
              return new Fraction(sign * n, 1);
          }
      
          if (1 - maxError < value)
          {
              return new Fraction(sign * (n + 1), 1);
          }
      
          // The lower fraction is 0/1
          int lower_n = 0;
          int lower_d = 1;
      
          // The upper fraction is 1/1
          int upper_n = 1;
          int upper_d = 1;
      
          while (true)
          {
              // The middle fraction is (lower_n + upper_n) / (lower_d + upper_d)
              int middle_n = lower_n + upper_n;
              int middle_d = lower_d + upper_d;
      
              if (middle_d * (value + maxError) < middle_n)
              {
                  // real + error < middle : middle is our new upper
                  upper_n = middle_n;
                  upper_d = middle_d;
              }
              else if (middle_n < (value - maxError) * middle_d)
              {
                  // middle < real - error : middle is our new lower
                  lower_n = middle_n;
                  lower_d = middle_d;
              }
              else
              {
                  // Middle is our best fraction
                  return new Fraction((n * middle_d + middle_n) * sign, middle_d);
              }
          }
      }
      
      public struct Fraction
      {
          public Fraction(int n, int d)
          {
              N = n;
              D = d;
          }
      
          public int N { get; private set; }
          public int D { get; private set; }
      }
      
      // real + error < middle : middle is our new upper
      Seek(ref upper_n, ref upper_d, lower_n, lower_d, (un, ud) => (lower_d + ud) * (value + maxError) < (lower_n + un));
      
      // middle < real - error : middle is our new lower
      Seek(ref lower_n, ref lower_d, upper_n, upper_d, (ln, ld) => (ln + upper_n) < (value - maxError) * (ld + upper_d));
      
      /// <summary>
      /// Binary seek for the value where f() becomes false.
      /// </summary>
      void Seek(ref int a, ref int b, int ainc, int binc, Func<int, int, bool> f)
      {
          a += ainc;
          b += binc;
      
          if (f(a, b))
          {
              int weight = 1;
      
              do
              {
                  weight *= 2;
                  a += ainc * weight;
                  b += binc * weight;
              }
              while (f(a, b));
      
              do
              {
                  weight /= 2;
      
                  int adec = ainc * weight;
                  int bdec = binc * weight;
      
                  if (!f(a - adec, b - bdec))
                  {
                      a -= adec;
                      b -= bdec;
                  }
              }
              while (weight > 1);
          }
      }
      
      Accuracy: 1.0E-3      | Stern-Brocot                             OPTIMIZED   | Eppstein                                 | Richards                                 
      Input                 | Result           Error       Iterations  Iterations  | Result           Error       Iterations  | Result           Error       Iterations  
      ======================| =====================================================| =========================================| =========================================
         0                  |       0/1 (zero)   0         0           0           |       0/1 (zero)   0         0           |       0/1 (zero)   0         0           
         1                  |       1/1          0         0           0           |    1001/1000      1.0E-3     1           |       1/1          0         0           
         3                  |       3/1          0         0           0           |    1003/334       1.0E-3     1           |       3/1          0         0           
        -1                  |      -1/1          0         0           0           |   -1001/1000      1.0E-3     1           |      -1/1          0         0           
        -3                  |      -3/1          0         0           0           |   -1003/334       1.0E-3     1           |      -3/1          0         0           
         0.999999           |       1/1         1.0E-6     0           0           |    1000/1001     -1.0E-3     2           |       1/1         1.0E-6     0           
        -0.999999           |      -1/1         1.0E-6     0           0           |   -1000/1001     -1.0E-3     2           |      -1/1         1.0E-6     0           
         1.000001           |       1/1        -1.0E-6     0           0           |    1001/1000      1.0E-3     1           |       1/1        -1.0E-6     0           
        -1.000001           |      -1/1        -1.0E-6     0           0           |   -1001/1000      1.0E-3     1           |      -1/1        -1.0E-6     0           
         0.50 (1/2)         |       1/2          0         1           1           |     999/1999     -5.0E-4     2           |       1/2          0         1           
         0.33... (1/3)      |       1/3          0         2           2           |     999/2998     -3.3E-4     2           |       1/3          0         1           
         0.67... (2/3)      |       2/3          0         2           2           |     999/1498      3.3E-4     3           |       2/3          0         2           
         0.25 (1/4)         |       1/4          0         3           3           |     999/3997     -2.5E-4     2           |       1/4          0         1           
         0.11... (1/9)      |       1/9          0         8           4           |     999/8992     -1.1E-4     2           |       1/9          0         1           
         0.09... (1/11)     |       1/11         0         10          5           |     999/10990    -9.1E-5     2           |       1/11         0         1           
         0.62... (307/499)  |       8/13        2.5E-4     5           5           |     913/1484     -2.2E-6     8           |       8/13        2.5E-4     5           
         0.14... (33/229)   |      15/104       8.7E-4     20          9           |     974/6759     -4.5E-6     6           |      16/111       2.7E-4     3           
         0.05... (33/683)   |       7/145      -8.4E-4     24          10          |     980/20283     1.5E-6     7           |      10/207      -1.5E-4     4           
         0.18... (100/541)  |      17/92       -3.3E-4     11          10          |     939/5080     -2.0E-6     8           |      17/92       -3.3E-4     4           
         0.06... (33/541)   |       5/82       -3.7E-4     19          8           |     995/16312    -1.9E-6     6           |       5/82       -3.7E-4     4           
         0.1                |       1/10         0         9           5           |     999/9991     -1.0E-4     2           |       1/10         0         1           
         0.2                |       1/5          0         4           3           |     999/4996     -2.0E-4     2           |       1/5          0         1           
         0.3                |       3/10         0         5           5           |     998/3327     -1.0E-4     4           |       3/10         0         3           
         0.4                |       2/5          0         3           3           |     999/2497      2.0E-4     3           |       2/5          0         2           
         0.5                |       1/2          0         1           1           |     999/1999     -5.0E-4     2           |       1/2          0         1           
         0.6                |       3/5          0         3           3           |    1000/1667     -2.0E-4     4           |       3/5          0         3           
         0.7                |       7/10         0         5           5           |     996/1423     -1.0E-4     4           |       7/10         0         3           
         0.8                |       4/5          0         4           3           |     997/1246      2.0E-4     3           |       4/5          0         2           
         0.9                |       9/10         0         9           5           |     998/1109     -1.0E-4     4           |       9/10         0         3           
         0.01               |       1/100        0         99          8           |     999/99901    -1.0E-5     2           |       1/100        0         1           
         0.001              |       1/1000       0         999         11          |     999/999001   -1.0E-6     2           |       1/1000       0         1           
         0.0001             |       1/9991      9.0E-4     9990        15          |     999/9990001  -1.0E-7     2           |       1/10000      0         1           
         1E-05              |       1/99901     9.9E-4     99900       18          |    1000/99999999  1.0E-8     3           |       1/99999     1.0E-5     1           
         0.33333333333      |       1/3         1.0E-11    2           2           |    1000/3001     -3.3E-4     2           |       1/3         1.0E-11    1           
         0.3                |       3/10         0         5           5           |     998/3327     -1.0E-4     4           |       3/10         0         3           
         0.33               |      30/91       -1.0E-3     32          8           |     991/3003      1.0E-5     3           |      33/100        0         2           
         0.333              |     167/502      -9.9E-4     169         11          |    1000/3003      1.0E-6     3           |     333/1000       0         2           
         0.7777             |       7/9         1.0E-4     5           4           |     997/1282     -1.1E-5     4           |       7/9         1.0E-4     3           
         0.101              |      10/99        1.0E-4     18          10          |     919/9099      1.1E-6     5           |      10/99        1.0E-4     3           
         0.10001            |       1/10       -1.0E-4     9           5           |       1/10       -1.0E-4     4           |       1/10       -1.0E-4     2           
         0.100000001        |       1/10       -1.0E-8     9           5           |    1000/9999      1.0E-4     3           |       1/10       -1.0E-8     2           
         0.001001           |       1/999       1.0E-6     998         11          |       1/999       1.0E-6     3           |       1/999       1.0E-6     1           
         0.0010000001       |       1/1000     -1.0E-7     999         11          |    1000/999999    9.0E-7     3           |       1/1000     -1.0E-7     2           
         0.11               |      10/91       -1.0E-3     18          9           |    1000/9091     -1.0E-5     4           |      10/91       -1.0E-3     2           
         0.1111             |       1/9         1.0E-4     8           4           |    1000/9001     -1.1E-5     2           |       1/9         1.0E-4     1           
         0.111111111111     |       1/9         1.0E-12    8           4           |    1000/9001     -1.1E-4     2           |       1/9         1.0E-12    1           
         1                  |       1/1          0         0           0           |    1001/1000      1.0E-3     1           |       1/1          0         0           
        -1                  |      -1/1          0         0           0           |   -1001/1000      1.0E-3     1           |      -1/1          0         0           
        -0.5                |      -1/2          0         1           1           |    -999/1999     -5.0E-4     2           |      -1/2          0         1           
         3.14               |      22/7         9.1E-4     6           4           |     964/307       2.1E-5     3           |      22/7         9.1E-4     1           
         3.1416             |      22/7         4.0E-4     6           4           |     732/233       9.8E-6     3           |      22/7         4.0E-4     1           
         3.14... (pi)       |      22/7         4.0E-4     6           4           |     688/219      -1.3E-5     4           |      22/7         4.0E-4     1           
         0.14               |       7/50         0         13          7           |     995/7107      2.0E-5     3           |       7/50         0         2           
         0.1416             |      15/106      -6.4E-4     21          8           |     869/6137      9.2E-7     5           |      16/113      -5.0E-5     2           
         2.72... (e)        |      68/25        6.3E-4     7           7           |     878/323      -5.7E-6     8           |      87/32        1.7E-4     5           
         0.141592653589793  |      15/106      -5.9E-4     21          8           |     991/6999     -7.0E-6     4           |      15/106      -5.9E-4     2           
        -1.33333333333333   |      -4/3         2.5E-15    2           2           |   -1001/751      -3.3E-4     2           |      -4/3         2.5E-15    1           
        -1.3                |     -13/10         0         5           5           |    -992/763       1.0E-4     3           |     -13/10         0         2           
        -1.33               |     -97/73       -9.3E-4     26          8           |    -935/703       1.1E-5     3           |    -133/100        0         2           
        -1.333              |      -4/3         2.5E-4     2           2           |   -1001/751      -8.3E-5     2           |      -4/3         2.5E-4     1           
        -1.33333337         |      -4/3        -2.7E-8     2           2           |    -999/749       3.3E-4     3           |      -4/3        -2.7E-8     2           
        -1.7                |     -17/10         0         5           5           |    -991/583      -1.0E-4     4           |     -17/10         0         3           
        -1.37               |     -37/27        2.7E-4     7           7           |    -996/727       1.0E-5     7           |     -37/27        2.7E-4     5           
        -1.33337            |      -4/3        -2.7E-5     2           2           |    -999/749       3.1E-4     3           |      -4/3        -2.7E-5     2           
         0.047619           |       1/21        1.0E-6     20          6           |    1000/21001    -4.7E-5     2           |       1/21        1.0E-6     1           
        12.125              |      97/8          0         7           4           |     982/81       -1.3E-4     2           |      97/8          0         1           
         5.5                |      11/2          0         1           1           |     995/181      -5.0E-4     2           |      11/2          0         1           
         0.1233333333333    |       9/73       -3.7E-4     16          8           |     971/7873     -3.4E-6     4           |       9/73       -3.7E-4     2           
         0.7454545454545    |      38/51       -4.8E-4     15          8           |     981/1316     -1.9E-5     6           |      38/51       -4.8E-4     4           
         0.01024801004      |       2/195       8.2E-4     98          9           |     488/47619     2.0E-8     13          |       2/195       8.2E-4     3           
         0.99011            |      91/92       -9.9E-4     91          8           |     801/809       1.3E-6     5           |     100/101      -1.1E-5     2           
         0.9901134545       |      91/92       -9.9E-4     91          8           |     601/607       1.9E-6     5           |     100/101      -1.5E-5     2           
         0.19999999         |       1/5         5.0E-8     4           3           |    1000/5001     -2.0E-4     2           |       1/5         5.0E-8     1           
         0.20000001         |       1/5        -5.0E-8     4           3           |    1000/4999      2.0E-4     3           |       1/5        -5.0E-8     2           
         5.0183168565E-05   |       1/19908     9.5E-4     19907       16          |    1000/19927001 -5.0E-8     2           |       1/19927     5.2E-12    1           
         3.909E-07          |       1/2555644   1.0E-3     2555643     23          |       1/1         2.6E6 (!)  1           |       1/2558199   1.1E-8     1           
      88900003.001          |88900003/1        -1.1E-11    0           0           |88900004/1         1.1E-8     1           |88900003/1        -1.1E-11    0           
         0.26... (5/19)     |       5/19         0         7           6           |     996/3785     -5.3E-5     4           |       5/19         0         3           
         0.61... (37/61)    |      17/28        9.7E-4     8           7           |     982/1619     -1.7E-5     8           |      17/28        9.7E-4     5           
                            |                                                      |                                          | 
      Accuracy: 1.0E-4      | Stern-Brocot                             OPTIMIZED   | Eppstein                                 | Richards                                 
      Input                 | Result           Error       Iterations  Iterations  | Result           Error       Iterations  | Result           Error       Iterations  
      ======================| =====================================================| =========================================| =========================================
         0.62... (307/499)  |     227/369      -8.8E-5     33          11          |    9816/15955    -2.0E-7     8           |     299/486      -6.7E-6     6           
         0.05... (33/683)   |      23/476       6.4E-5     27          12          |    9989/206742    1.5E-7     7           |      23/476       6.4E-5     5           
         0.06... (33/541)   |      28/459       6.6E-5     24          12          |    9971/163464   -1.9E-7     6           |      33/541        0         5           
         1E-05              |       1/99991     9.0E-5     99990       18          |   10000/999999999 1.0E-9     3           |       1/99999     1.0E-5     1           
         0.333              |     303/910      -9.9E-5     305         12          |    9991/30003     1.0E-7     3           |     333/1000       0         2           
         0.7777             |     556/715      -1.0E-4     84          12          |    7777/10000      0         8           |    1109/1426     -1.8E-7     4           
         3.14... (pi)       |     289/92       -9.2E-5     19          8           |    9918/3157     -8.1E-7     4           |     333/106      -2.6E-5     2           
         2.72... (e)        |     193/71        1.0E-5     10          9           |    9620/3539      6.3E-8     11          |     193/71        1.0E-5     7           
         0.7454545454545    |      41/55        6.1E-14    16          8           |    9960/13361    -1.8E-6     6           |      41/55        6.1E-14    5           
         0.01024801004      |       7/683       8.7E-5     101         12          |    9253/902907   -1.3E-10    16          |       7/683       8.7E-5     5           
         0.99011            |     100/101      -1.1E-5     100         8           |     901/910      -1.1E-7     6           |     100/101      -1.1E-5     2           
         0.9901134545       |     100/101      -1.5E-5     100         8           |    8813/8901      1.6E-8     7           |     100/101      -1.5E-5     2           
         0.26... (5/19)     |       5/19         0         7           6           |    9996/37985    -5.3E-6     4           |       5/19         0         3           
         0.61... (37/61)    |      37/61         0         10          8           |    9973/16442    -1.6E-6     8           |      37/61         0         7           
      
      public Fraction RealToFraction(double value, int maxDenominator)
      {
          // http://www.ics.uci.edu/~eppstein/numth/frap.c
          // Find rational approximation to given real number
          // David Eppstein / UC Irvine / 8 Aug 1993
          // With corrections from Arno Formella, May 2008
      
          if (value == 0.0)
          {
              return new Fraction(0, 1);
          }
      
          int sign = Math.Sign(value);
      
          if (sign == -1)
          {
              value = Math.Abs(value);
          }
      
          int[,] m = { { 1, 0 }, { 0, 1 } };
          int ai = (int) value;
      
          // Find terms until denominator gets too big
          while (m[1, 0] * ai + m[1, 1] <= maxDenominator)
          {
              int t = m[0, 0] * ai + m[0, 1];
              m[0, 1] = m[0, 0];
              m[0, 0] = t;
              t = m[1, 0] * ai + m[1, 1];
              m[1, 1] = m[1, 0];
              m[1, 0] = t;
      
              value = 1.0 / (value - ai);
      
              // 0x7FFFFFFF = Assumes 32 bit floating point just like in the C implementation.
              // This check includes Double.IsInfinity(). Even though C# double is 64 bits,
              // the algorithm sometimes fails when trying to increase this value too much. So
              // I kept it. Anyway, it works.
              if (value > 0x7FFFFFFF)
              {                    
                  break;
              }
      
              ai = (int) value;
          }
      
          // Two approximations are calculated: one on each side of the input
          // The result of the first one is the current value. Below the other one
          // is calculated and it is returned.
      
          ai = (maxDenominator - m[1, 1]) / m[1, 0];
          m[0, 0] = m[0, 0] * ai + m[0, 1];
          m[1, 0] = m[1, 0] * ai + m[1, 1];
      
          return new Fraction(sign * m[0, 0], m[1, 0]);
      }
      
      public Fraction RealToFraction(double value, double accuracy)
      {
          if (accuracy <= 0.0 || accuracy >= 1.0)
          {
              throw new ArgumentOutOfRangeException("accuracy", "Must be > 0 and < 1.");
          }
      
          int maxDenominator = (int) Math.Ceiling(Math.Abs(1.0 / (value * accuracy)));
      
          if (maxDenominator < 1)
          {
              maxDenominator = 1;
          }
      
          return RealToFraction(value, maxDenominator);
      }
      
      /// <summary>
          /// Converts Decimals into Fractions.
          /// </summary>
          /// <param name="value">Decimal value</param>
          /// <returns>Fraction in string type</returns>
          public string DecimalToFraction(double value)
          {
              string result;
              double numerator, realValue = value;
              int num, den, decimals, length;
              num = (int)value;
              value = value - num;
              value = Math.Round(value, 5);
              length = value.ToString().Length;
              decimals = length - 2;
              numerator = value;
              for (int i = 0; i < decimals; i++)
              {
                  if (realValue < 1)
                  {
                      numerator = numerator * 10;
                  }
                  else
                  {
                      realValue = realValue * 10;
                      numerator = realValue;
                  }
              }
              den = length - 2;
              string ten = "1";
              for (int i = 0; i < den; i++)
              {
                  ten = ten + "0";
              }
              den = int.Parse(ten);
              num = (int)numerator;
              result = SimplifiedFractions(num, den);
              return result;
          }
      
          /// <summary>
          /// Converts Fractions into Simplest form.
          /// </summary>
          /// <param name="num">Numerator</param>
          /// <param name="den">Denominator</param>
          /// <returns>Simplest Fractions in string type</returns>
          string SimplifiedFractions(int num, int den)
          {
              int remNum, remDen, counter;
              if (num > den)
              {
                  counter = den;
              }
              else
              {
                  counter = num;
              }
              for (int i = 2; i <= counter; i++)
              {
                  remNum = num % i;
                  if (remNum == 0)
                  {
                      remDen = den % i;
                      if (remDen == 0)
                      {
                          num = num / i;
                          den = den / i;
                          i--;
                      }
                  }
              }
              return num.ToString() + "/" + den.ToString();
          }
      }
      
      inline unsigned int richards_solution(double const& x0, unsigned long long& num, unsigned long long& den, double& sign, double const& err = 1e-10){
          sign = my::sign(x0);
          double g(std::abs(x0));
          unsigned long long a(0);
          unsigned long long b(1);
          unsigned long long c(1);
          unsigned long long d(0);
          unsigned long long s;
          unsigned int iter(0);
          do {
              s = std::floor(g);
              num = a + s*c;
              den = b + s*d;
              a = c;
              b = d;
              c = num;
              d = den;
              g = 1.0/(g-s);
              if(err>std::abs(sign*num/den-x0)){ return iter; }
          } while(iter++<1e6);
          std::cerr<<__PRETTY_FUNCTION__<<" : failed to find a fraction for "<<x0<<std::endl;
          return 0;
      }
      
      inline unsigned int btilly_solution(double x, unsigned long long& num, unsigned long long& den, double& sign, double const& err = 1e-10){
          sign = my::sign(x);
          num  = std::floor(std::abs(x));
          x = std::abs(x)-num;
          unsigned long long lower_n(0);
          unsigned long long lower_d(1);
          unsigned long long upper_n(1);
          unsigned long long upper_d(1);
          unsigned long long middle_n;
          unsigned long long middle_d;
          unsigned int iter(0);
          do {
              middle_n = lower_n + upper_n;
              middle_d = lower_d + upper_d;
              if(middle_d*(x+err)<middle_n){
                  upper_n = middle_n;
                  upper_d = middle_d;
              } else if(middle_d*(x-err)>middle_n) {
                  lower_n = middle_n;
                  lower_d = middle_d;
              } else {
                  num = num*middle_d+middle_n;
                  den = middle_d;
                  return iter;
              }
          } while(iter++<1e6);
          den = 1;
          std::cerr<<__PRETTY_FUNCTION__<<" : failed to find a fraction for "<<x+num<<std::endl;
          return 0;
      }
      
      ------------------------------------------------------ |
      btilly  0.166667 0.166667=1/6 in 5 iterations          | 1/6
      richard 0.166667 0.166667=1/6 in 1 iterations          |
      ------------------------------------------------------ |
      btilly  0.333333 0.333333=1/3 in 2 iterations          | 1/3
      richard 0.333333 0.333333=1/3 in 1 iterations          |
      ------------------------------------------------------ |
      btilly  0.142857 0.142857=1/7 in 6 iterations          | 1/7
      richard 0.142857 0.142857=1/7 in 1 iterations          |
      ------------------------------------------------------ |
      btilly  0.714286 0.714286=5/7 in 4 iterations          | 5/7
      richard 0.714286 0.714286=5/7 in 4 iterations          |
      ------------------------------------------------------ |
      btilly  1e-07 1.001e-07=1/9990010 in 9990009 iteration | 0.0000001
      richard 1e-07 1e-07=1/10000000 in 1 iterations         |
      ------------------------------------------------------ |
      btilly  3.66667 3.66667=11/3 in 2 iterations           | 11/3
      richard 3.66667 3.66667=11/3 in 3 iterations           |
      ------------------------------------------------------ |
      btilly  1.41421 1.41421=114243/80782 in 25 iterations  | sqrt(2)
      richard 1.41421 1.41421=114243/80782 in 13 iterations  |
      ------------------------------------------------------ |
      btilly  3.14159 3.14159=312689/99532 in 317 iterations | pi
      richard 3.14159 3.14159=312689/99532 in 7 iterations   |
      ------------------------------------------------------ |
      btilly  2.71828 2.71828=419314/154257 in 36 iterations | e
      richard 2.71828 2.71828=517656/190435 in 14 iterations |
      ------------------------------------------------------ |
      btilly  0.390885 0.390885=38236/97819 in 60 iterations | random
      richard 0.390885 0.390885=38236/97819 in 13 iterations |
      
       namespace my{
          template<typename Type> inline constexpr
              int sign_unsigned(Type x){ return Type(0)<x; }
      
          template<typename Type> inline constexpr
              int sign_signed(Type x){ return (Type(0)<x)-(x<Type(0)); }
      
          template<typename Type> inline constexpr
              int sign(Type x) { return std::is_signed<Type>()?sign_signed(x):sign_unsigned(x); }
       }
      
          public static string toFraction(string exp) {
              double x = Convert.ToDouble(exp);
              int sign = (Math.Abs(x) == x) ? 1 : -1;
              x = Math.Abs(x);
              int n = (int)x; // integer part
              x -= n; // fractional part
              int mult, nm, dm;
              int decCount = 0;
      
              Match m = Regex.Match(Convert.ToString(x), @"([0-9]+?)\1+.?$");
              // repeating fraction
              if (m.Success) {
                  m = Regex.Match(m.Value, @"([0-9]+?)(?=\1)");
                  mult = (int)Math.Pow(10, m.Length);
      
                  // We have our basic fraction
                  nm = (int)Math.Round(((x * mult) - x));
                  dm = mult - 1;
              }
              // get the number of decimal places
              else {
                  double t = x;
                  while (t != 0) {
                      decCount++;
                      t *= 10;
                      t -= (int)t;
                  }
                  mult = (int)Math.Pow(10, decCount);
      
                  // We have our basic fraction
                  nm = (int)((x * mult));
                  dm = mult;
              }
              // can't be simplified
              if (nm < 0 || dm < 0) return exp;
      
              //Simplify
              Stack factors = new Stack();
              for (int i = 2; i < nm + 1; i++) {
                  if (nm % i == 0) factors.Push(i);  // i is a factor of the numerator
              }
              // check against the denominator, stopping at the highest match
              while(factors.Count != 0) {
                  // we have a common factor
                  if (dm % (int)factors.Peek() == 0) {
                      int f = (int)factors.Pop();
                      nm /= f;
                      dm /= f;
                      break;
                  }
                  else factors.Pop();
              }
              nm += (n * dm);
              nm *= sign;
              if (dm == 1) return Convert.ToString(nm);
              else return Convert.ToString(nm) + "/" + Convert.ToString(dm);
          }
      
          Ex: 28.66666
          28*9=252
          252+6=258
          258/9=28.66666
      
      public Fraction RealToFraction(double value, double accuracy)
      {
          if (accuracy <= 0.0 || accuracy >= 1.0)
          {
              throw new ArgumentOutOfRangeException("accuracy", "Must be > 0 and < 1.");
          }
      
          int sign = Math.Sign(value);
      
          if (sign == -1)
          {
              value = Math.Abs(value);
          }
      
          // Accuracy is the maximum relative error; convert to absolute maxError
          double maxError = sign == 0 ? accuracy : value * accuracy;
      
          int n = (int) Math.Floor(value);
          value -= n;
      
          if (value < maxError)
          {
              return new Fraction(sign * n, 1);
          }
      
          if (1 - maxError < value)
          {
              return new Fraction(sign * (n + 1), 1);
          }
      
          double z = value;
          int previousDenominator = 0;
          int denominator = 1;
          int numerator;
      
          do
          {
              z = 1.0 / (z - (int) z);
              int temp = denominator;
              denominator = denominator * (int) z + previousDenominator;
              previousDenominator = temp;
              numerator = Convert.ToInt32(value * denominator);
          }
          while (Math.Abs(value - (double) numerator / denominator) > maxError && z != (int) z);
      
          return new Fraction((n * denominator + numerator) * sign, denominator);
      }
      
      public func decimalToFraction(_ d: Double) -> (Int, Int) {
          var df: Double = 1
          var top: Int = 1
          var bot: Int = 1
      
          while df != d {
              if df < d {
                  top += 1
              } else {
                  bot += 1
                  top = Int(d * bot)
              }
              df = top / bot
          }
          return (top, bot)
      }
      
      public func realToFraction(_ value: Double, accuracy: Double = 0.00005) -> (Int, Int)? {
          var value = value
          guard accuracy >= 0 && accuracy <= 1 else {
              Swift.print(accuracy, "Must be > 0 and < 1.")
              return nil
          }
          let theSign = sign(value)
          if theSign == -1 {
              value = abs(value)
          }
      
          // Accuracy is the maximum relative error; convert to absolute maxError
          let maxError = theSign == 0 ? accuracy : value * accuracy
      
          let n = floor(value)
          value -= n
      
          if value < maxError {
              return (Int(theSign * n), 1)
          }
      
          if 1 - maxError < value {
              return (Int(theSign * (n + 1)), 1)
          }
      
          // The lower fraction is 0/1
          var lowerN: Double = 0
          var lowerD: Double = 1
      
          // The upper fraction is 1/1
          var upperN: Double = 1
          var upperD: Double = 1
      
          while true {
              // The middle fraction is (lowerN + upperN) / (lowerD + upperD)
              let middleN = lowerN + upperN
              let middleD = lowerD + upperD
      
              if middleD * (value + maxError) < middleN {
                  // real + error < middle : middle is our new upper
                  upperN = middleN
                  upperD = middleD
              } else if middleN < (value - maxError) * middleD {
                  // middle < real - error : middle is our new lower
                  lowerN = middleN
                  lowerD = middleD
              } else {
                  // Middle is our best fraction
                  return (Int(n * middleD + middleN * theSign), Int(middleD))
              }
          }
      }
      
      public static string DoubleToFraction(double num)
      {            
          if (Math.Round(num, 6) == Math.Round(num, 0))
              return Math.Round(num, 0).ToString();
          bool minus = (num < 0) ? true : false;
          int up;
          if (minus)
              up = (int)((Math.Round(num, 6) - 0.000001) * 362880);
          else
              up = (int)((Math.Round(num, 6) + 0.000001) * 362880);
          int down = 362880;
          int div = gcd(up, down);
          up /= div;
          down /= div;
          return up + "/" + down;
      }
      public static int gcd(int a, int b)
      {
          if (b == 0)
              return Math.Abs(a);
          return gcd(b, a % b);
      }
      
      def float_to_fraction (x, error=0.000001):
          n = int(math.floor(x))
          x -= n
          if x < error:
              return (n, 1)
          elif 1 - error < x:
              return (n+1, 1)
          # The lower fraction is 0/1
          lower_n = 0
          lower_d = 1
          # The upper fraction is 1/1
          upper_n = 1
          upper_d = 1
          while True:
              # The middle fraction is (lower_n + upper_n) / (lower_d + upper_d)
              middle_n = lower_n + upper_n
              middle_d = lower_d + upper_d
              # If x + error < middle
              if middle_d * (x + error) < middle_n:
                  # middle is our new upper
                  upper_n = middle_n
                  upper_d = middle_d
              # Else If middle < x - error
              elif middle_n < (x - error) * middle_d:
                  # middle is our new lower
                  lower_n = middle_n
                  lower_d = middle_d
              # Else middle is our best fraction
              else:
                  #return (n * middle_d + middle_n, middle_d)
                  frac = Fraction(n * middle_d + middle_n, middle_d)
                  if (frac.numerator // frac.denominator) == 0:
                      return(f"{frac.numerator % frac.denominator}/{frac.denominator}")
                  elif ((frac.numerator % frac.denominator)/frac.denominator) == 0/1:
                      return(f"{frac.numerator // frac.denominator}")
                  else:
                      return(f"{frac.numerator // frac.denominator} "f"{frac.numerator % frac.denominator}/{frac.denominator}")```
      
      function float_to_fraction(x, error = 0.00001) {
       const n = Math.floor(x);
       x -= n;
      
       if (x < error) {
         return `${n}`;
       } else if (1 - error < x) {
         return `${n + 1}`;
       }
      
       //  The lower fraction is 0/1
       let lower_n = 0;
       let lower_d = 1;
      
       // The upper fraction is 1/1
       let upper_n = 1;
       let upper_d = 1;
       while (true) {
         // The middle fraction is (lower_n + upper_n) / (lower_d + upper_d)
         let middle_n = lower_n + upper_n;
         let middle_d = lower_d + upper_d;
         // If x + error < middle
         if (middle_d * (x + error) < middle_n) {
           // middle is our new upper
           upper_n = middle_n;
           upper_d = middle_d;
           // Else If middle < x - error
         } else if (middle_n < (x - error) * middle_d) {
           // middle is our new lower
           lower_n = middle_n;
           lower_d = middle_d;
           //Else middle is our best fraction
         } else {
           return `${n * middle_d + middle_n}/${middle_d}`;
         }
       }
      }