【问题标题】:Division in base N以 N 为底的除法
【发布时间】:2016-03-18 11:33:51
【问题描述】:

我想知道在 C 中是否有特定的算法可以做到这一点。 不过我想出了一些方法。

问题:我有 2 个以 7 为底的数字。这些数字是可整除的,所以我的答案总是一个整数。我想计算商。

最简单的方法可能是将我在基数 10 中的两个数字从基数 7 转换,然后使用 / 运算符进行正常除法,然后将答案重新转换回基数 7。

这种方法有很多缺点,耗时过长,主要是溢出。如果除数的长度超过大约 (17-19),则转换为以 10 为底的数字将不适合 long long int。

看了很多之后,一个简单的方法是重复乘法。 示例 202 和 13 我可以在基数 7 中重复添加 13,直到必须添加多次才能得到 202。这就是答案。但是我无法思考如何将这些相乘。

我在寻求什么帮助?:算法/伪代码或代码(C/C++,因为这是我知道的唯一语言),用于除以两个数字,并获得以 7 为底的商。结果将是一个完美的整数。

非常感谢。

#define max 2000

long long int bconvert(long long int x) //conversion from base 7 to decimal
{   long long int i=0,ans=0;
    while(x>0)
    {
    ans+=(x%10)*pow(7,i);
    x/=10;
    i++;
}
return ans;
}

 int main() {
long long int A,B,L,a,b,c,C,arr[max],i,j,k,arr1[max],r;
    scanf("%lld %lld %lld",&A,&B)
    a=bconvert(A);
    b=bconvert(B);
    c=a/b; //decimal division
    k=0;
    C=0;
    while(c>0)
    {
        r=c%7;
        c/=7;
        C+=r*pow(10,k);
        k++;
    }
    cout<<C<<endl;

输出是以 7 为底的商,形式与输入相同。

【问题讨论】:

  • 实际上有一种比机械计算器时代使用的直接重复乘法更快的方法,类似于长除法。至于实际的加法/乘法,您可以只拥有一个数字数组并一次使用一个数字列。
  • 你的以 7 为基数的数字是如何表示的?
  • 是的,但这会导致溢出。我正在划分的数字的长度非常大,将超出 long long int 的范围。如果我可以直接转换解决它,那么这个问题就没有意义了。
  • 我的红利可以有大约 10^3-6 的长度(整数形式)。除数可以说是 10^4-5。我正在尝试为较小的情况考虑一个解决方案,例如数字的整数形式的长度约为 20 位(大约在它刚刚溢出时)(被除数),所以很明显除数的长度约为(
  • 7^22 仍小于 2^64。

标签: c base integer-division base-conversion


【解决方案1】:

我在寻求什么帮助?:算法/伪代码或代码(C/C++,如 那是我知道的唯一语言)用于两个数字的除法,以及 得到一个以 7 为底的商。

不要把以 7 为底的数字解释为以 10 为底的数字。相反,根据输入和输出的真实基数转换数字;这很简单。

#include <stdio.h>
#include <stdlib.h>

long long scanbase7()
{
    char str[24];
    return scanf("%23s", str) > 0 ? strtoll(str, NULL, 7) : -1;
}

void printbase7(long long n)
{
    long long p = 1;
    while (n/p > 7) p *= 7;
    do putchar('0'+n/p), n %= p; while (p /= 7);
    puts("");
}

int main()
{
    long long a, b, c;
    a = scanbase7();
    b = scanbase7();
    c = a/b;
    printbase7(c);
}

【讨论】:

    【解决方案2】:

    抱歉,没有时间发布完整的代码(今天稍后会做这么多),但以下至少是“字符串”划分的一个很好的概述。

    #include <stdlib.h>
    #include <string.h>
    
    // Assume no illegal characters
    char *strdivide(char *quotient, const char *dividend, const char *divisor, 
        unsigned base) {
      // consume leading zeros
      while (*dividend == '0' && dividend[1]) dividend++;
      while (*divisor == '0' && divisor[1]) divisor++;
      // Detect /0
      if (strcmp(divisor, "0")==0) {
        return "Division by 0";
      }
      // Detect dividend obviousl smaller than divisor
      size_t dd_size = strlen(dividend);
      size_t dv_size = strlen(divisor);
      if (dd_size < dv_size) {
        return strcpy(quotient, "0");
      }
    
      // Work with copy of dividend
      char div[dd_size + 1];
      memcpy(div, dividend, dd_size + 1);
    
      // Form quotient
      size_t places = dd_size - dv_size;
      for (size_t i = 0; i<=places; i++) {
        // Assume ASCII
        int digit = 0;
        while (strcmp(div, divisor) >= 0)) {
          int borrow = 0;
          for (unsigned j = dv_size; j-- > 0; ) {
            int diff = value(div[j]) - value(divisor[j]) - borrow;
            if (diff < 0) {
              diff += base;
              borrow = 1;
            } else {
              borrow = 0;
            }
            div[j] = unvalue(diff);
          }
        }
        quotient[i] = unvlaue(digit); // int to char
      }
      quotient[i] = '\0';
      // Check for leading 0 in `quotient[]`, shift if needed.
      return quotient;
    }
    

    【讨论】:

    • 我已经添加了我自己的代码,但是,它在某些情况下给出了错误的答案,并在少数情况下是正确的。有什么机会可以解决吗?
    【解决方案3】:

    您可以直接在输入字符串上实现long division algorithm

    另一种选择是将数字转换为以 16807 (7**5) 为基数的任意精度整数,在该基数中进行除法并将结果转换回以 7 为基数。

    【讨论】:

    • 我可以将收到的整数转换为数字字符串,但是,我在为基数 7 编写长除法代码时遇到了很多困难。至于转换,我没有知道如何进行这些转换,但除此之外,如果数字的字符串表示的顺序长度约为 25
    猜你喜欢
    • 1970-01-01
    • 2014-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-24
    • 2021-01-28
    • 1970-01-01
    相关资源
    最近更新 更多