【问题标题】:Array Division - What is the best way to divide two numbers stored in an array?数组除法 - 将存储在数组中的两个数字相除的最佳方法是什么?
【发布时间】:2011-03-20 07:47:46
【问题描述】:

我有两个数组(除数,除数):

dividend[] = {1,2,0,9,8,7,5,6,6};
divisor[] = {9,8};

我需要结果(除数/除数)为:

quotient[] = {1,2,3,4,5,6,7};

我使用数组减法来做到这一点:

  • 从被除数中减去除数,直到被除数变为 0 或小于除数,每次将商增加 1,

但这需要很长时间。有没有更好的方法来做到这一点?

【问题讨论】:

  • 我不完全确定我是否理解 - 您如何从您提供的除数和除数示例中获得商数组?您的除数数组和除数数组的长度是否不同?如果是这样,您如何映射除数数组中的哪个数组元素与您的除数数组匹配?
  • @Adam:显然他将 120987566 除以 98 得到 1234567。问题是各个十进制数字存储在数组中。正如 James 在下面建议的那样,他可以像小学所教的那样实现 long 除法

标签: c++ c algorithm arrays digits


【解决方案1】:

给你! A 是股息。 B 是除数。 C 是整数商 R是其余的。 每个“大”数都是一个保留大数的向量。在 huge[0] 中,我们保留了数字的位数,然后将数字向后记忆。 假设我们有数字 1234,那么 corespoding 向量将是:

v[0]=4; //number of digits
v[1]=4;
v[2]=3;
v[3]=2;
v[4]=1;

....

SHL(H,1) does: H=H*10;
SGN(A,B) Compares the A and B numbers
SUBSTRACT(A,B) does: A=A-B;
DIVIDHUGE: makes the division using the mentioned procedures...

void Shl(Huge H, int Count)
/* H <- H*10ACount */
{ 
  memmove(&H[Count+1],&H[1],sizeof(int)*H[0]);
  memset(&H[1],0,sizeof(int)*Count);
   H[0]+=Count;
}
    int Sgn(Huge H1, Huge H2) {
      while (H1[0] && !H1[H1[0]]) H1[0]--;
      while (H2[0] && !H2[H2[0]]) H2[0]--;

      if (H1[0] < H2[0]) {
        return -1;
      } else if (H1[0] > H2[0]) {
        return +1;
      }

      for (int i = H1[0]; i > 0; --i) {
        if (H1[i] < H2[i]) {
          return -1;
        } else if (H1[i] > H2[i]) {
          return +1;
        }
      }
      return 0;
    }

        void Subtract(Huge A, Huge B)
        /* A <- A-B */
        { int i, T=0;

          for (i=B[0]+1;i<=A[0];) B[i++]=0;
          for (i=1;i<=A[0];i++)
            A[i]+= (T=(A[i]-=B[i]+T)<0) ? 10 : 0;
          while (!A[A[0]]) A[0]--;
        }


            void DivideHuge(Huge A, Huge B, Huge C, Huge R)
            /* A/B = C rest R */
            { int i;

              R[0]=0;C[0]=A[0];
              for (i=A[0];i;i--)
                { Shl(R,1);R[1]=A[i];
                  C[i]=0;
                  while (Sgn(B,R)!=1)
                    { C[i]++;
                      Subtract(R,B);
                    }
                }
              while (!C[C[0]] && C[0]>1) C[0]--;
            }

【讨论】:

    【解决方案2】:

    你可以使用长除法http://en.wikipedia.org/wiki/Long_division

    【讨论】:

      【解决方案3】:

      除此之外,您是否考虑过使用 BigInt 类(或您的语言中的等价物)已经可以为您做到这一点?

      【讨论】:

      • BigInt 类仅适用于我猜想的 Java,而在 C++ 中,我不知道有任何用途。
      • GNU MP Bignum 库怎么样 - gmplib.orgGMP is a free library for arbitrary precision arithmetic, operating on signed integers, rational numbers, and floating point numbers
      • 是的,还有 OpenSSL 的 BigNum 库。
      【解决方案4】:

      做长除法。

      有一个大小等于除数加一的临时存储,并初始化为零:

      accumulator[] = {0,0,0};
      

      现在运行一个循环:

      1. 将商的每个数字左移一个空格。
      2. 将累加器的每个数字右移一个空格。
      3. 取除数的下一位,从最高有效端开始,并将其存储到累加器的最低有效位。
      4. 找出accumulator / divisor 并将商的最不重要的位置设置为结果。将累加器设置为余数。

      过去常常在汇编语言中为没有除法指令的 CPU 使用相同的算法。

      【讨论】:

      • 这带来了相关的问题,“你如何计算累加器/除数?”
      • 使用重复的减法,但使用这种方法你会做大约 40 个而不是 1,234,567 个。
      • 我不记得确切的技巧,但是 Knuth 展示了一种方法,每个商位数不超过两个减法(而不是这里的 40)。 TAOCP 卷。 2 我认为。
      【解决方案5】:

      为什么不将它们转换为整数,然后使用正则除法?

      在伪代码中:

      int dividend_number
      foreach i in dividend
          dividend_number *= 10
          dividend_number += i
      
      int divisor_number
      foreach i in divisor
          divisor_number *= 10
          divisor_number += i
      
      int answer = dividend_number / divisor_number;
      

      【讨论】:

      • 这样很容易造成溢出。如果 OP 可以做到这一点,他可能一开始就不会使用数组。
      • 没错,我正在使用 100 位数字。
      • 我认为关键是数组中的数字代表 BigInts,也就是说,它们有可能比整数大得多。
      • 啊,还以为这是个学术练习。看起来他应该使用类似 GMP 的东西,不是吗?
      【解决方案6】:

      您可以使用Long division algorithm 或更通用的Polynomial Long Division

      【讨论】:

        【解决方案7】:

        有没有更好的方法来做到这一点?

        您可以使用long division

        【讨论】:

          猜你喜欢
          • 2010-10-17
          • 2010-12-17
          • 1970-01-01
          • 2020-04-08
          • 2016-08-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多