欢迎光临散文网 会员登陆 & 注册

【TIS-100 攻略】TIS-NET 第 19 关:十进制转八进制转换器

2022-11-11 01:46 作者:ココアお姉ちゃん  | 我要投稿

本文首发于 B 站《TIS-100》文集(https://www.bilibili.com/read/readlist/rl626023)。原创不易,转载请注明出处。

TIS-NET 第 19 关《十进制转八进制转换器》(Decimal to Octal Coverter)关卡展示

本关需要把收到的十进制数转成八进制的形式输出。八进制即【逢 8 进 1】,十进制下逢 10 进 1 的规则在八进制下变成了逢 8 进 1,举例说明:十进制的 7 在八进制下也是 7,但十进制的 8,由于触发了逢 8 进 1 的规则,在八进制下会产生进位,变成 10。类似的道理,十进制下的 64,八八六十四,低位进了 8 次位后,高位变成了 8 也会向它的更高位进 1,所以十进制的 64 在八进制下需要用三位数表示,即 100。

本关的输入量在 0~63 之间,所以输出的八进制最多也只有两位数。由于逢 8 进 1,所以八进制的高位其实表示的是【这个数里有多少个 8】。也就是说这其实又是道除法题,高位是原数除以 8 的商,低位则是对应的余数。

除法嘛,老规矩,线性查找法和二分查找法各说一遍。

线性查找法

将原数不断减去 8,每减去一个 8,就令答案的高位加上 1,直到减到负数为止。代码如下:

上方和中央节点纯传话(mov up down, mov up down)。然后看左下角节点:

  1. 左下角的节点收到 IN 中的数字后(mov up acc),

  2. 不断减 8(sub 8),判断是否减到了负数。

  3. 若减到了负数,则跳到第 6 行执行(jlz 6)。

  4. 尚未减到负数时,按顺序执行,向右边发送 -1 信号(mov -1 right),

  5. 并跳回第 2 行继续减(jmp 2)。

  6. 直到减到负数后,向右边发送 1 信号(mov 1 right),

  7. 并将减到了负数的被除数发给右边(mov acc right)。

现在看右下角节点:

  1. 右下角的节点先将 acc 初始化为 8(mov -2 acc)

  2. (add 10)

  3. 然后听从左边节点的指令(jro left)。左边发送 -1 时,说明原数减 8 尚未减到负数,我们往回跳 1 行,令八进制的高位加 1(add 10);

  4. 左边发送 1 时,说明原数减到了负数,我们将这个负数加回一个 8 后,得到原数除以 8 的余数,将它作为八进制数的低位。由于初始值已经将低位置为了 8,所以直接加上左边发来的负数,就把最终的低位设置好了(add left)。

  5. 最后,将计算好的八进制数发往下方的 OUT 口(mov acc down)。

点击左下角的【RUN】,稍等片刻,便会弹出结算界面:

二分查找法

由于原始数字在 0~63 范围,除以 8 的商在 0~7 范围,二分查找法最多计算 %5Clog_2%208%3D3%20 次即可得出结论。算法如下:

  • 设原始数字为 a。

  • 若 a >= 32,则令 b = a-32,令八进制的高位加上 4,否则令 b = a;

  • 若 b >= 16,则令 c = b-16,令八进制的高位加上 2,否则令 c = b;

  • 若 c >= 8,则令 d = c-8,令八进制的高位加上 1,否则令 d = c;

  • 将八进制的低位置为 d 并输出。

代码如下:

先看左下角的节点:

  1. 左下角的节点首先计算 a-32 的值(mov -32 acc)

  2. (add up)

  3. 然后检查该值是否小于 0:若该值小于 0,则令 b = a(acc 相当于 b-32),同时八进制的高位不变。现在的 acc 是 b-32 的值,为了将 acc 变为 b-16,我们需要跳到第 6 行,将 acc 加回一个 16(jlz 6, add 16)。

  4. 若该值大于等于 0,则令 b = a-32(acc 已经是 b),同时需要令八进制的高位加上 4。我们向右边发送 -2 信号,令右边将八进制的高位加上 4(mov -2 right)。

  5. 同时,因为下一步要判定 b 是否大于等于 16,即 b-16 是否大于等于 0,我们需要提前将 acc 表示的 b 减去 16(sub 32)

  6. (add 16)

  7. 接下来判断 b-16 是否小于 0:若该值小于 0,则令 c = b(acc 相当于 c-16),同时八进制的高位不变。现在的 acc 是 c-16 的值,为了将 acc 变为 c-8,我们需要跳到第 10 行,将 acc 加回一个 8(jlz a, add 8)。

  8. 若该值大于等于 0,则令 c = b-16(acc 已经是 c),同时需要令八进制的高位加上 2。我们向右边发送 -1 信号,令右边将八进制的高位加上 2(mov -1 right)。

  9. 同时,因为下一步要判定 c 是否大于等于 8,即 c-8 是否大于等于 0,我们需要提前将 acc 表示的 c 减去 8(sub 16)

  10. (add 8)

  11. 接下来判断 c-8 是否小于 0:若该值小于 0,则令 d = c(acc 相当于 d-8),同时八进制的高位不变。因为紧接着要发送的 acc 是 d-8 的值,我们跳到第 14 行(jlz e),先向右边发送一个 2 信号,令右边提前加上一个 8(mov 2 right),然后再将这个 d-8 的值发给右边,让右边顺理成章地将八进制的低位设置为 8+d-8=d 的值(mov acc right)。

  12. 若该值大于等于 0,则令 d = c-8(acc 已经是 d),同时需要令八进制的高位加上 1。我们向右边发送 1 信号,令右边将八进制的高位加上 1,再将低位设置为 d(mov 1 right, jmp f, mov acc right)。

右下角的节点:开幕跳到第 4 行(jmp 4)的 jro 指令处(jro left),然后会收到左边发来的 4 种指令中的 1 种。之前解释左下角节点的代码时都说过了,这里再汇总一下:

  • 收到 -2 时,令八进制的高位加上 4,此时我们往上跳 2 行,将 acc 加上 40(add 20, add 20);

  • 收到 -1 时,令八进制的高位加上 2。此时我们往上跳 1 行,将 acc 加上 20(add 20);

  • 收到 1 时,令八进制的高位加上 1,且已知接下来收到的是 d 值。此时我们往下跳 1 行,将 acc 加上 10(add 2, add 8),再加上接下来发来的 d 值并输出给 OUT 口(add left, mov acc down);

  • 收到 2 时,八进制的高位不变,且已知接下来收到的是 d-8 的值。此时我们向下跳 2 行,将 acc 提前加上 8(add 8),再加上接下来发来的 d-8,成功将低位置为 d 后,输出给 OUT 口(add left, mov acc down)。

点击左下角的【RUN】,稍等片刻,便会弹出结算界面:


【TIS-100 攻略】TIS-NET 第 19 关:十进制转八进制转换器的评论 (共 条)

分享到微博请遵守国家法律