Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.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#_Algorithm_Optimization_Math_Mathematical Optimization - Fatal编程技术网

C# 在一定范围内计算最大有理分式

C# 在一定范围内计算最大有理分式,c#,algorithm,optimization,math,mathematical-optimization,C#,Algorithm,Optimization,Math,Mathematical Optimization,我试图在一个只接受积分买入/卖出金额的市场上进行与精确汇率匹配的货币交易。我想以特定的价格进行最大的交易。这是一个玩具程序,不是真正的交易机器人,所以我用的是C 我需要一个算法,即使分子和分母可能很大(100000+),也能在合理的时间内返回答案 我问了一个类似的问题(http://stackoverflow.com/questions/4385580/finding-the-closest-integer-fraction-to-a-given-random-real)在我思考我真正想要完成的

我试图在一个只接受积分买入/卖出金额的市场上进行与精确汇率匹配的货币交易。我想以特定的价格进行最大的交易。这是一个玩具程序,不是真正的交易机器人,所以我用的是C

我需要一个算法,即使分子和分母可能很大(100000+),也能在合理的时间内返回答案


我问了一个类似的问题(http://stackoverflow.com/questions/4385580/finding-the-closest-integer-fraction-to-a-given-random-real)在我思考我真正想要完成的事情之前,结果是我试图解决一个不同但相关的问题

如果你想要未缩减的分数,那么你可以做一个优化:因为你永远不会对n/2感兴趣,因为你想要2n/4、4n/8或1024n/2048,我们只需要检查一些数字。只要我们检查2的任意倍数,我们就不需要检查2。因此,我相信您可以通过
分母max/2
尝试使用分母
分母max/2
,并且您将隐式检查这些数字的所有因子,即通过
分母max/2
的所有值

我现在还没有在编译,所以我还没有检查这段代码的正确性,甚至没有检查它是否编译过,但应该很接近

static bool CalcBiggestRationalFraction(float target_real, float epsilon, 
    int numerator_max, int denominator_max, 
    out int numerator, out int denominator)
{
    if((int)Math.Round(target_real * denominator_max) > numerator_max)
    {
        // We were given values that don't match up.
        // For example, target real = 0.5, but max_num / max_den = 0.3
        denominator_max = (int)(numerator_max / target_real);
    }

    float bestEpsilon = float.MAX_VALUE;
    for(int den = denominator_max; den >= denominator_max/2, den--)
    {
        int num = (int)Math.Round(target_real * den);
        float thisEpsilon = Math.abs(((float)num / den) - target_real);
        if(thisEpsilon < bestEpsilon)
        {
            numerator = num;
            denominator = den;
            bestEpsilon = thisEpsilon;
        }
    }

    return bestEpsilon < epsilon;
}
static bool-calcbigestrationalfraction(float-target\u-real,float-epsilon,
整数分子,整数分母,
out int分子,out int分母)
{
if((int)数学四舍五入(target_real*分母_max)>分子_max)
{
//我们得到的值不匹配。
//例如,target real=0.5,但max_num/max_den=0.3
分母_max=(int)(分子_max/目标_real);
}
float bestEpsilon=float.MAX_值;
对于(int den=分母最大值;den>=分母最大值/2,den--)
{
int num=(int)Math.Round(target_real*den);
float thisEpsilon=Math.abs(((float)num/den)-target_real);
if(此ε<最佳ε)
{
分子=num;
分母=den;
最佳ε=此ε;
}
}
返回最佳ε<ε;
}
让我们试试这个:

首先,我们需要把浮子变成一个分数。我能想到的最简单的方法是找到ε的数量级,将浮点数乘以该数量级,然后截断得到分子

long orderOfMagnitude = 1
while(epsilon * orderOfMagnitude <1)
   orderOfMagnitude *= 10;

numerator = (int)(target_real*orderOfMagnitude);
denominator = orderOfMagnitude;

//sanity check; if the initial fraction isn't within the epsilon, then add sig figs until it is
while(target_real - (float)numerator / denominator > epsilon)
{
   orderOfMagnitude *= 10;
   numerator = (int)(target_real*orderOfMagnitude);
   denominator = orderOfMagnitude;
}
长量级=1

虽然(epsilon*orderOfMagnitude解决问题的标准方法是使用。特别是,请参见。

为什么不分解浮点数并从中重构分数?有趣的问题,让我看看我是否能想出一些办法。我想这是你的另一个问题的重复,我看不出有什么区别,只是一些标记和文本发生了变化,但是你想要的东西是重复的。你能举个例子吗?你想要精确匹配的最大分数分量,还是想要+/-epsilon范围内可能的绝对最大分数?他说他不想要最低项,他明确想要最高项。CalcBiggestRationalFraction(.5)应该返回2/4,而不是1/2。我认为这不会找到最好的分数。假设它通过了target_real=1/3,epsilon=0.01。上半部分将找到分数33/100,下半部分将尝试减少该分数(已经减少,没有公因子)。如果我读对了,它永远不会尝试3的分母。@David:首先,“最高术语”是一个用词不当;2/4=4/8=8/16=16/32=…你明白了;2/4不是“最高术语”,没有一个分数不能乘以2/2得到一个具有更大项的等价分数。他说他想要的是最接近浮点数的分数,而且绝对在ε范围内。你在第二点上是对的,但从技术上讲,在计算机中,如果不猜测数字r是合理的。这个算法,IMO,在不猜测数据的情况下得到最接近的分数。你是对的,“最高项”是一个用词不当的词,但只能单独使用。他传入了
max_分母
,并给出了一个具体的例子,用max_分母为4计算0.5的分数,结果应该是2/4,而不是1/2。你不需要假设这个数字是合理的:例如,在0.01范围内计算Pi将得到314/100,这将减少到157/50。然而,355/113更接近,精确到0.000001。我想要一个形式的答案:n/d。不是嵌套连续分数。当结果(减少)时,停止扩展分数满足您的精度要求。有一种算法可以为连续分数扩展的连续级别生成减少的N/D-抱歉,我并没有链接。
long orderOfMagnitude = 1
while(epsilon * orderOfMagnitude <1)
   orderOfMagnitude *= 10;

numerator = (int)(target_real*orderOfMagnitude);
denominator = orderOfMagnitude;

//sanity check; if the initial fraction isn't within the epsilon, then add sig figs until it is
while(target_real - (float)numerator / denominator > epsilon)
{
   orderOfMagnitude *= 10;
   numerator = (int)(target_real*orderOfMagnitude);
   denominator = orderOfMagnitude;
}
var primes = new List<int>{2,3,5,7,11,13,17,19,23}; //to start us off

var i = 0;
while (true)
{
   if(Math.Sqrt(numerator) < primes[i] || Math.Sqrt(denominator) < primes[i]) break;

   if(numerator % primes[i] == 0 && denominator % primes[i] == 0)
   {
      numerator /= primes[i];
      denominator /= primes[i];
      i=0;
   }
   else
   {
      i++;
      if(i > primes.Count)
      {
        //Find the next prime number by looking for the first number not divisible
        //by any prime < sqrt(number).
        //We are actually unlikely to have to use this, because the denominator
        //is a power of 10, so its prime factorization will be 2^x*5^x
        var next = primes.Last() + 2;
        bool add;
        do
        {
           add = true;
           for(var x=0; primes[x] <= Math.Sqrt(next); x++)
              if(next % primes[x] == 0)
              {
                add = false;
                break;
              }

           if(add)
              primes.Add(next);
           else
              next+=2;   
        } while(!add);
      }
   }
}