【问题标题】:Calculate exponents via addition only仅通过加法计算指数
【发布时间】:2009-12-13 23:30:46
【问题描述】:

我们正在编写一个非常简单的程序,以便在我们为一个类构建的处理器上执行。它没有乘法或除法的能力。但是,我们确实支持循环控制的加法、减法、和、或和分支(如果您熟悉 MIPS,则如相等的分支)。我们在想一个可以在上面运行的简洁程序应该是某种 x^n 程序。当然,这些数字必须进行硬编码,但考虑到我们处理器的限制,这是否现实?

是否有仅用于指数的加法计算? 谢谢。

【问题讨论】:

  • 如果你有移位指令,很容易很快地做乘法和除法。
  • 我们没有轮班指令。现在我正在考虑它实际上也不是特别困难。它只是不是必需的。

标签: algorithm mips addition exponent


【解决方案1】:

对于小整数,为什么不呢?

首先,使用重复加法实现乘法。然后,使用重复乘法实现 pow() 。它会很慢,但会正常工作。

有一种更快的求幂算法,称为Exponentiation by Squaring。但是,鉴于您没有快速乘法,我不确定这是否值得 - 您可能希望首先实现快速乘法算法。

【讨论】:

  • 如果你有位移指令,你同样可以实现更快的“倍增”。
  • 你可以在没有位移指令的情况下通过加倍来实现乘法:a+a == a
  • @Nick:但是没有右移,你怎么知道要执行多少次?
【解决方案2】:

符合 dmazzoni 在 c 样式语法中的响应:

int mulitply(int x, int y)
{
    int product;

    for (int i = 0; i<y; i++)
       product += x;

    return product;
}

int power(int x, int exponent)
{
    int result = 1;

    for (int i = 0; i < exponent; i++)
        result = multiply(result, x);

    return result;
}

【讨论】:

  • 哎呀,我刚刚意识到我制定了一个非常相似的解决方案。无论如何都向我 +1
【解决方案3】:

类似于 Aequitarum 的解决方案,但对幂使用重复平方,对乘法使用重复加倍。对于大 x,y 应该更快:

int multiply(int x, int y) {
  int product = 0;
  int bitmask = 1;

  while (y >= bitmask) {
    if (y & bitmask) product += x;
    x += x;
    bitmask += bitmask;
  }
  return product;
}

int power(int x, int exponent)
{
  int result = 1;
  int bitmask = 1;

  while (exponent >= bitmask) {
    if (exponent & bitmask) result = multiply(result, x);
    x = multiply(x, x);
    bitmask += bitmask;
  }
  return result;
}

【讨论】:

    【解决方案4】:

    这是非常现实的。几年前,处理器还没有可以执行任何高级运算(如乘法和除法)的 ALU。

    乘法通常使用移位和加法来完成。这是一些伪汇编:

    ; multiply registers a and b
    
    ; use c as high b
    mov c,#0
    ; use d as low result
    mov d,#0
    ; use e as high result
    mov e,#0
    .nextbit:
      ; shift low bit out of a
      shr a
      ; skip if zero
      bcc .noadd
        ; add b to result
        add d,b
        adc e,c
      .noadd:
      ; double b
      shl b
      rcl c
      ; test a
      cmp a,#0
    bne .nextbit
    

    (注意两个字节值相乘的结果是一个两个字节值。)

    一旦你有了乘法,你就可以循环计算幂。

    使用说明:

    mov x,y = move y into x
    shr x = shift right one bit
    shl x = shift left one bit
    rcl x = rotate left one bit with carry inserted
    add x,y = add y to x
    adc x,y = add y to x with carry
    cmp x,y = compare x to y
    bcc = branch on carry clear
    bne = branch on not equal
    #0 = literal number zero (as opposed to 0, which would be the address zero)
    

    【讨论】:

      【解决方案5】:

      您可以在Multiplication ALU 上找到相关的维基百科文章。通过加法和按位运算(and and or),您可以一步一步地实现乘法运算,而不必像较小运算符的大小一样多次相加。

      【讨论】:

        【解决方案6】:

        n 的 k 次幂:

        exponent(n,k) {
           for(x=1..n)
              x = x + exponent(x,k-1)
        }
        

        【讨论】:

          猜你喜欢
          • 2019-03-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-06-12
          • 2018-08-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多