【问题标题】:Finding a square root using only integers仅使用整数求平方根
【发布时间】:2013-05-13 23:18:07
【问题描述】:

最近,我在某人的编程课上遇到了一个问题。它要求他们仅使用整数计算平方根;他们要用一个整数表示小数点前的部分,用另一个整数表示小数点后的部分。问题是不允许使用浮点数。

但是,经过一段时间的思考,我似乎无法想出一种不使用浮点的方法。我用谷歌搜索了很多,但似乎找不到答案。

我开玩笑地建议我的朋友实现一个 FPU 来执行此操作,但他并不那么好笑。

有人对如何解决这个问题有任何想法吗?

【问题讨论】:

标签: integer square-root


【解决方案1】:

假设您的原始号码是x

  1. 查找小数点前的部分很容易 - 只需找到最大数,即小于或等于原始数的平方。

  2. 将原始数字乘以 100,将 sqrt 的整数部分乘以 10。将其加 1 直到小于或等于 100x。执行n 次并在最后除以10^n 以将最终答案截断为n 小数位。

【讨论】:

  • 这似乎不适用于 sqrt(2)。我得到 1. 很好,但是第一个十进制数字是 3(1 * 10 = 10,小于 10 的最大平方是 3),而不是 4(sqrt(2) = 1.414
  • 是的,我现在意识到了。因为这里乘以 10 是错误的……它是平方根,而 10 不是一个完美的平方。已编辑,这次应该是对的……
【解决方案2】:

假设您有一个算法可以创建两个整数AB,这样A / B 的比率就会为您提供所需的平方根近似值到适当的小数位数。然后,您想要的两个数字将是:

  • 整数部分为(A - (A % B)) / B
  • 小数部分:设XA % B。然后配给X / B 代表小数部分。然后通过计算(10*X - (10*X % B)) / B 和设置X = (10*X % B) 来构建连续的数字来计算小数部分,直到获得所需的小数位数。

要导出平方根的所需分数近似值,您可以计算平方根的连分数。

【讨论】:

    【解决方案3】:

    在伪代码中是这样的:

    int whole_ans = sqrt(num); //stores final answer integer part
    int dec_ans; //stores final answer decimal part
    
    int num_of_decimals = x   //x is equal to the number of decimal places you want the answer to be
    int targetNum = (num - (whole_ans^2)) * 100;  //initialize target to residual * 100
    int currAns = whole_ans; //initialize target to residual of num - the answer so far
    
    for(int i=0;i<x;i++)
    {
        x = get_next_digit(targetNum,currAns));
        dec_ans = append(dec_ans, x);  //append the new found digit to the right of the current decimal answer
        targetNum = (targetNum - (currAns * 20 + x) * x) * 100; //update target number to be residual + 2 zero digits
        currAns = append(currAns,dec_ans) //append the decimal part of the answer to the current total answer so far
    
    }
    
    func get_next_digit(targetNum,currAns)
    {
    int attempt=0;
    int i=0;
       while(attempt <= targetNum)
       {
           i++;
           attempt = (20 * currAns + i) * i;
       }
    i--;
    return i;
    }
    

    此答案遵循手动计算平方根的步骤:http://www.wikihow.com/Calculate-a-Square-Root-by-Hand

    【讨论】:

      【解决方案4】:

      假设您要计算 123.4567 的平方根。

      那么您所要做的就是将小数点向右移动足够远以获得整数radicand - 在这个例子中,四个位置 - 所以,以下是正确的:

      sqrt(123.4567) = (1/100) * sqrt(1234567)

      也就是说,您只需要知道如何求整数的平方根。为此,请考虑以下代码(C 语言):

      unsigned int int_sqrt (unsigned int n) {
      
          unsigned int result = 0;
          unsigned int count  = 1;
      
          for (; count*count <= n; count += 1) {
      
              result = result + 1;
      
          }
      
          return result;
      
      }
      

      如果你想取消乘法,你也可以这样做:

      unsigned int int_sqrt (unsigned int n) {
      
          unsigned int result = 0;
          unsigned int odd    = 1;
          unsigned int oddsum = 1;
      
          while (oddsum <= n) {
      
              result = result + 1;
              odd = odd + 2;
              oddsum = oddsum + odd;
      
          }
      
          return result;
      
      }
      

      这些显然不是最快的方法——但它们只使用整数,并且不依赖于特定 CPU 的特性,例如字长。

      【讨论】:

        【解决方案5】:

        我相信二进制搜索的修改形式将帮助您实现这一目标。 让我用 c 代码详细说明一下。

        int square_number = findSquareRootFloor(GivenValue);

        int findSquareRootFloor(int number)
        {
            int low = 0;
            int high = number;
            int mid = 0;
            while (low <= high)
            {
                int mid = (high + low) / 2;
                int target = mid * mid;
                if (target > number)
                    high = mid - 1;
                else if (target < number)
                    low = mid +1;
                else
                   // exact match
                   return mid;
            }
         
            // if we have come here mid stores the floor of the square root
            return high;
        }
        

        【讨论】:

          猜你喜欢
          • 2021-12-09
          • 1970-01-01
          • 1970-01-01
          • 2012-06-07
          • 2013-11-05
          • 2015-03-04
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多