如何为Fibonacci编写寄存器机器代码

时间:2013-05-28 18:24:24

标签: algorithm

我不确定这是否是提出这个问题的正确位置,但由于它涉及编程和代码,希望这是正确的地方。

我曾试图在程序员和计算机科学SE上发帖,但他们将我重定向到了这个网站。

问题是如何编写计算Fibonacci数的寄存器机器代码/程序。代码的语法实际上非常简单。

(以下仅供参考,对不起,长篇大论)
(有关更多解释,请参阅正式逻辑:理查德卡尔杰弗里的范围和限制)

根据维基百科,寄存器机器是一种抽象机器的通用类,其使用方式类似于图灵机。 (处理器)寄存器是少量存储器,可作为CPU或其他数字处理器的一部分使用。

我们可以通过将寄存器建模为空桶来简化问题,我们可以将大理石或岩石放入寄存器(“桶”)。规则是从桶中添加或移除弹珠以执行计算。

规则是:
1.一台登记机器使用有限数量的桶和无休止的大理石供应 2.每个桶都可以单独识别。大理石无需区分 注册机程序是一组有限的指令:
- 将大理石添加到桶中(然后继续下一条指令) - 或者从桶里拿出一块大理石(并继续下一个) 如果你能,或另一个,如果你不能,请指示。) 4.程序可以用流程图或指令列表编写。

以下是执行添加的注册机程序的示例 让A,B,C成为桶 1.(-B; 2,4)表示从桶B中取出一块大理石,如果可以,则转到指令2,如果不能,则转到4 2.(+ A; 3)表示将一个大理石添加到桶A中,然后转到指令3
3.(+ C; 1)表示将一个大理石添加到铲斗C中,然后转到指令1
4.(-C; 5, - )表示从桶C中取出一个大理石,如果可以则转到指令2,如果不能则退出 5.(+ B; 4)表示将一个大理石添加到桶B中,然后转到指令4

很容易证明,在桶A中有3个弹珠,在桶B中有2个弹珠,在桶C中有4个弹珠。执行该算法后,将有| A | + | B |。 = 3 + 2 =桶A中的5个弹珠和| B | + | C | = 2 + 4 =桶B中有6个弹珠。

(我希望上面的例子足够清楚以便于说明)

(现在问题来了)

现在,我想编写一个寄存器机器代码,当在存储桶A中输入n时,返回(也在存储桶A中)第n个斐波纳契数。 Fibonacci数字是0(第0),1(第1),1 = 0 + 1(第2)等。我们可以使用任意数量的桶,目标是尽可能简单地编写代码(即最少的指示)。给定F(0)= 0且F(1)= 1,斐波纳契递归关系为F(n)= F(n-1)+ F(n-2)。

这是我的尝试和代码:
我的想法是使用桶A作为输入,最后作为输出F(n)(因为问题需要桶A中的输出),桶B作为“计数器”,桶C作为F(n-1)和桶D如F(n-2)。
1.(+ C; 2)
2.(-A; 3,4)
3.(+ B; 2)
4.(-D; 5,7)
5.(+ A; 4)
6.(-C; 5,7)
7.(-B; 6, - )

但是我的代码只能用于n = 2,遗憾的是,我正在努力使代码适用于任何n> 2。

我一直想着这个日日夜夜,如果有人能帮助我,我将不胜感激。如果有任何不清楚的地方,请不要犹豫要求我澄清。

许多人提前感谢!

4 个答案:

答案 0 :(得分:4)

下面是一些示例Python代码,用于模拟在11条指令中执行任务的注册机:

# Store loop counter in 4
# Store F(n) in 1
# Store F(n+1) in 2
# Redistribute 2 to 1 and 3 to get F(n+1)+F(n),0,F(n+1)
# then move back to the order F(n+1),F(n+1)+F(n),0
code={1:(-1,2,3),   # Move n to 
      2:(+4,1),     #    bin 4 to act as loop counter
      3:(+2,4),     # Initialise bin 2 with F(1)=1
      4:(-4,5,0),   # Check for completion
      5:(-2,6,8),   # redistribute F(n+1)
      6:(+1,7),     #    to bin 1
      7:(+3,5),     #    and bin 3
      8:(-1,9,10),  # Move bin 1 to
      9:(+2,8),     #    bin 2
      10:(-3,11,4), # and bin 3
      11:(+1,10)}   #    to bin 1

def fib(n):
    buckets=[0,n,0,0,0]
    instruction_pointer = 1
    while instruction_pointer:
        ins = code[instruction_pointer]
        x = ins[0]
        if x>0:
            buckets[x]+=1
            instruction_pointer = ins[1]
        else:
            x=-x
            if buckets[x]>0:
                buckets[x]-=1
                instruction_pointer = ins[1]
            else:
                instruction_pointer = ins[2]
    return buckets[1]

for n in xrange(10):
    print n,fib(n)

答案 1 :(得分:2)

我会对此采取行动。由于您需要机器代码,最简单的方法是编写相对较低级别的伪代码,并从那里开始工作到机器代码。您需要考虑的主要事项是如何制作if语句,如何将一个寄存器设置为等于另一个寄存器以及如何进行循环。

我几乎可以保证有更有效的方法来做到这一点,但这应该是一个开始。

这是我要做的伪代码,假设你已经有了预期的迭代次数,> 2,在寄存器'n'中:

A = 0
B = 1
C = 1
DO
  A = B + C // Note, this is really A = 0, A += B, A += C
  C = B  // Similarly, C = 0, C += B
  B = A  // B = 0, B += A
WHILE N- > 0

这不应该变成寄存器代码:

1.   B+, 2 // B = 1
2.   C+, 3 // C = 1
3.   A-, 3, 4 // Get A down to 0 - not necessary, just here for clarity
4.   D-, 4, 5 // Get temporary variable D down to 0. - not necessary, just here for clarity
5.   B-, 6, 8 // Copy B into A (part of adding) and temporary variable D
6.     A+, 7  // A = B
7.     D+, 5  // D = B
8.   C-, 9, 10 // Add C into A = B
9.     A+, 8  // A += C
10.  N-, 11, -// Check your N count
11.    D-, 12, 13 // Copy D (the old B) into C
12.      C+, 11  // C = D
13.    A-, 14, 5 // Copy A into B
14.      B+, 13  // B = A

你可以看到我保留了两条我不需要的行,在那里我初始化了A和D.因为它们从0开始并且每个循环读取到0,所以这些行是不必要的,最终结果是:

1.   B+, 2                       // B = 1
2.   C+, 3                       // C = 1
3.   B-, 4, 6 // Copy B into A (part of adding) and temporary variable D
4.     A+, 5                     // A = B
5.     D+, 3                     // D = B
6.   C-, 7, 8 // Add C into A = B
7.     A+, 6                     // A += C
8.   N-, 9, -// Check your N count, or exit
9.     D-, 10, 11 // Copy D (the old B) into C
10.      C+, 9                   // C = D
11.    A-, 12, 3 // Copy A into B
12.      B+, 12                  // B = A

同样,我确信它并不完美,但它应该让你接近。希望这有帮助!

修改

重新阅读这个问题,我看到“N”从A开始。我的算法不适用于此,所以我需要在前面添加两行来移动它。另外,我看到我的格式与原始OP不匹配,所以我修改了我的匹配(给出或取出间距和注释):

1.   (-A; 2, 3) // Move the "N" value out of A into N
2.     (+N; 1)                     // N = A
3.   (+B; 4)                       // B = 1
4.   (+C; 5)                       // C = 1
5.   (-B; 6, 8) // Copy B into A (part of adding) and temporary variable D
6.     (+A; 7)                     // A = B
7.     (+D; 5)                     // D = B
8.   (-C; 9, 10) // Add C into A = B
9.     (+A; 8)                     // A += C
10.  (-N; 11, -)// Check your N count, or exit
11.    (-D; 11, 13) // Copy D (the old B) into C
12.      (+C; 11)                   // C = D
13.    (-A; 14, 5) // Copy A into B
14.      (+B; 13)                   // B = A

答案 2 :(得分:0)

好的,我认为这将有效(如果它不让我知道,我将尝试修复它。)一个函数运行后,只需继续下一行(所以之后F1运行并返回,立即开始F2)

Buckets:
A: Initial Value and Final Answer
B: First Counter
C: Second Counter
D: Adding bucket
I: Copy of C for next iteration
J: temporary bucket used for copying

1: +B,3 //loads the first counter
2: +C,4 //loads the second counter
3: -A,3,L
4: F1, 4
5: F2, 5
6: F3, 3

F1:: //makes a copy of C
  Fa: -C,Fb,Fd
  Fb: +I,Fcv //I is now the copy of C
  Fc: +J,Fa
  Fd: -J,Ff,Fg
  Ff: +C,fd
  Fg: return

F2:: //Sums B and C
  Fa: -B,Fc,Fb //adds up B 
  Fb: -C,Fd,Fe //adds up C
  Fc: +D,Fa
  Fd: +D,Fb 
  Fe: -D,Ff,Fg
  Ff: +C,Fe //Copies result to C
  Fg: return

F3:: //copys old C into B
  Fa: -I,Fb,Fc
  Fb: +B,Fa
  Fc: //return

L:: //puts value of C into A for result
  Fa: -C,Fb,DONE
  Fb: +A,Fa

答案 3 :(得分:0)

根据您可以实施的宏指令进行书写。

实际上,您只需要一个宏指令来完成此任务,并且您已经拥有它(添加)。将存储桶清零是微不足道的(逐个移除弹珠),因此将存储桶的内容复制到另一个存储桶(零然后添加)。