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_Math_Fractions - Fatal编程技术网

C# 找到最小的整数,当它与已知的双精度相乘时,将产生一个整数

C# 找到最小的整数,当它与已知的双精度相乘时,将产生一个整数,c#,algorithm,math,fractions,C#,Algorithm,Math,Fractions,我有一个双输入a。我的目标是找到一个整数b,这样a*b将产生一个整数,加上一些允许的误差量。例如,100.227273*22=2205+0.000006错误,其中我想要找到的答案是22 我已经研究过了,但我只部分理解了最重要的答案。我真的需要一些帮助来创建一个算法来完成这项任务。我在下面有一些代码,它适用于某些情况,但不是所有情况 private int FindSmallestMultiplier(double input) { int numerator =

我有一个双输入a。我的目标是找到一个整数b,这样a*b将产生一个整数,加上一些允许的误差量。例如,100.227273*22=2205+0.000006错误,其中我想要找到的答案是22

我已经研究过了,但我只部分理解了最重要的答案。我真的需要一些帮助来创建一个算法来完成这项任务。我在下面有一些代码,它适用于某些情况,但不是所有情况

    private int FindSmallestMultiplier(double input)
    {
        int numerator = 1;
        int temp;
        double output = input;
        double invert = input;
        int denominator = 1;
        List<int> whole = new List<int>();
        double dec = input;
        int i = -1;
        while (Math.Abs(Math.Round(numerator * input)-numerator*input) > 0.001)
        {
            i = i + 1;
            //seperate out the whole and decimal portions of the input
            whole.Add(Convert.ToInt32(Math.Floor(invert)));
            dec = output - whole[i];
            //get the decimal portion of the input, and invert
            invert =  1 / dec;

            //create nested fraction to determine how far off from a whole integer we are
            denominator = 1;
            numerator = 1;
            for(int j = whole.Count-1; j >= 0; j--)
            {
                temp = whole[j] * denominator + numerator;
                numerator = denominator;
                denominator = temp;
            }
        }
        return numerator;
    }

上面的代码适用于许多输入情况,例如0.3333、0.5。它不起作用的一个例子是0.75或0.101,这只是无限中的一对。请帮助我找出我的代码有什么问题,或者提供一个代码示例以产生所需的结果。谢谢大家!

以下是链接问题中描述的方法的示例实现。If迭代计算连分数的新系数。这样做,它会检查重建的数字是否达到所需的精度。如果是,它返回重构分数的分母作为结果

// Reconstructs a fraction from a continued fraction with the given coefficients
static Tuple<int, int> ReconstructContinuedFraction(List<int> coefficients)
{
    int numerator = coefficients.Last();
    int denominator = 1;

    for(int i = coefficients.Count - 2; i >= 0; --i)
    {
        //swap numerator and denominator (= invert number)
        var temp = numerator;
        numerator = denominator;
        denominator = temp;

        numerator += denominator * coefficients[i];
    }
    return new Tuple<int, int>(numerator, denominator);
}

static int FindSmallestMultiplier(double input, double error)
{
    double remainingToRepresent = input;
    List<int> coefficients = new List<int>();
    while (true)
    {
        //calculate the next coefficient
        var integer = (int)Math.Floor(remainingToRepresent);                
        remainingToRepresent -= integer;
        remainingToRepresent = 1 / remainingToRepresent;
        coefficients.Add(integer);

        //check if we reached the desired accuracy
        var reconstructed = ReconstructContinuedFraction(coefficients);

        var multipliedInput = input * reconstructed.Item2;
        var multipliedInputRounded = Math.Round(multipliedInput);
        if (Math.Abs(multipliedInput - multipliedInputRounded) < error)
            return reconstructed.Item2;
    }
}
。。。提供以下输出:

3.14159265358979 * 113 = 354.999969855647

为什么?这根本上是有缺陷的。int是基数10。浮点数和双点数是基数2。这意味着double不能准确地表示int可以表示的每一个数字。@Zer0 int的基数是10吗?它仍然用二进制表示。@NicoSchertler计算机中的一切都是二进制的。众所周知,浮点数和双精度是基数2@Zer0当然。我不明白你的意思。每个32位整数都可以表示为64位双精度整数,尾数为52位。无论如何,这不是这个问题的重点。@NicoSchertler我提到这一点是因为整数乘以double得到double。还有很多以10为基数的数字,二进制浮点无法准确表示,因此在比较结果时使用了delta。谢谢你的解决方案。这看起来是一个非常干净的方法。
3.14159265358979 * 113 = 354.999969855647