【问题标题】:How to mimic logical XOR in ZX Spectrum basic?如何在 ZX Spectrum basic 中模拟逻辑异或?
【发布时间】:2018-02-16 06:20:35
【问题描述】:

有时在 ZX Spectrum Basic 中编码时,我需要评估由两个操作数和一个逻辑异或形成的逻辑表达式,如下所示:

IF (left operand) xor (right operand) THEN

由于 ZX Basic 只知道 NOT、OR 和 AND,我不得不求助于某种奇特的计算,其中包括左/右操作数的多次使用。这很尴尬,因为它消耗时间和内存,如果您在 8 位机器上工作,这两者都是稀疏的。我想知道是否有模仿 xor 运算符的巧妙技巧。

为了测试结果,我提供了一个小代码示例:

 5 DEF FN x(a,b)=(a ??? b) : REM the xor formula, change here
10 FOR a=-1 TO 1 : REM left operand
20 FOR b=-1 TO 1 : REM right operand
30 LET r=FN x(a,b) : REM compute xor
40 PRINT "a:";a;" b:";b;" => ";r
50 NEXT b
60 NEXT a

您能帮我找到一个高效的解决方案吗?到目前为止,我尝试了DEF FN x(a,b)=(a AND NOT b) OR (b AND NOT a),但它有点笨拙。

编辑:

如果您想测试您的想法,我建议您使用BasinC v1.69 ZX 模拟器(仅限 Windows)。

正如@Jeff 指出的大多数基础知识,例如 ZX 的,确实将零值视为 false,将非零值视为 true

我已调整样本以使用各种非零值进行测试。

【问题讨论】:

  • 逻辑上,NOT(A AND B) AND (A OR B) ?
  • @Worse_Username 可以工作,但它并没有加速我到目前为止的代码。 ^^
  • 我喜欢下面的<> 答案,但如果 ZX BASIC 支持函数式 IF-ELSE,另一个纯粹合乎逻辑的可能性是 IF A THEN (NOT B) ELSE (B) - 在 C 中,你可以写a?!b:b
  • @JeffZeitlin 我也喜欢<> 的答案,但它并不能解决所有情况。事实上,我有类似 50 IF a THEN GOTO 100 60 IF NOT b... 100 IF b THEN ... 之类的语句模仿三元运算符,但所有的 goto 都使这成为维护的噩梦。
  • 我还在寻找简洁的解决方案,请随时回答。欢迎任何想法。

标签: logical-operators xor basic retro-computing zxspectrum


【解决方案1】:

逻辑异或在语义上等同于不等于。

IF (left operand) <> (right operand) THEN

应该可以。

编辑:对于整数操作数,您可以使用

IF ((left operand) <> 0) <> ((right operand) <> 0) THEN

【讨论】:

  • 很好的答案 - 非常简洁
  • 这个不错。我应该在 ZX 上添加它,例如-1 评估为真。所以仍然存在需要考虑 -1 xor 1 的极端情况。但尽管如此,答案是正确的。
  • 大多数 BASIC 似乎认为零为假,非零为真。鉴于此,我不确定您为什么认为 -1 XOR 1 是“边缘案例”。
  • 嗯,我明白了。所以毕竟不是那么前卫,真的。
  • 我已经根据这个需要对其进行了调整。
【解决方案2】:

请记住,值是整数: 我认为数学运算可能很有趣: (A-B)*(A-B) 应该可以 基于简单的操作,它应该更少耗时。

或带 ABS : ABS (A-B)

【讨论】:

  • 这行不通,因为 A 和 B 不只是 0 或 1。在 Basic 中,如果 0,则操作数为 True。例如,如果 A 为 2,B 为 -1,您仍然需要A xor B 计算结果为 0(假)。
  • 它适用于提供的示例 :) 这取决于您管理布尔值的方式。基本上很容易通过使用 A AND A 或 A OR A 将其转换为布尔形式。
  • 是的,问题是关于这个的。找到一种高效的方法来获取布尔形式 0/1 并执行 xor。也许是 SGN,idk?
【解决方案3】:
DEF FN x(a,b)=((NOT a) <> (NOT b))

使用NOT 强制转换为布尔值。

EDIT 以前每一方都有NOT NOT,这对于建立两者之间的区别是不必要的,因为仍然会强制!

EDIT 2添加括号来解决优先级问题。

【讨论】:

  • 我刚刚意识到它只需要一个 NOT 在每一侧。相应地进行了编辑。
  • 随着你的更新,我现在得到一个 0 和 a=-1b=0,因为 NOT 的优先级较低。你甚至测试过你的任何提议吗?
  • 对不起,我无法获取安装环境。添加了括号,应该排序。
  • 仍有一些可以挤压的括号,但现在看起来可以接受。
  • 对不起,我已经有一段时间了。到目前为止,我可以从您的回答中得出的最短版本是:DEF FN x(a,b)=(NOT a) &lt;&gt; NOT b
【解决方案4】:

考虑到这个问题和这里的答案非常有趣和有趣,我想分享一些性能测试的结果(在模拟器上进行):

经过的时间以秒为单位,越少越好。 x1 test 只是看表达式是否满足要求并包含打印结果,x256 重复相同的测试 256 次不打印任何输出; without FN 测试是相同的,但没有在 FN 语句中考虑表达式。

我也分享 the code and test suite on github: https://github.com/rondinif/XOR-in-ZX-Spectrum-basic 以造福所有复古计算狂热者(..like 我)并分享我们的意见

【讨论】:

  • 我已经尽力了,但目前我已经进行了一些检查,可能会无意中犯下非自愿的错误;如果您看到可能的改进,您可以在 github 或 fork-it/pull-request 上打开问题。
  • Franco,如果您已经设置了基础架构,您可以试试我的性能答案吗?
  • @Ed。 (NOT a <> NOT b) 表现不错,我更新了答案和 git repo。
  • 我认为,如果我们消除您的数字 5(因为它仅适用于 1 和 0,并非 BASIC 中的所有有效布尔值),我的两个(数字 3 和 7)是最快的吗?
  • 到目前为止,我可以从 Eds 的答案中得出的最短版本是:DEF FN x(a,b)=(NOT a) &lt;&gt; NOT b。把它放在桌子上会很棒。 @FrancoRondini
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-08
  • 1970-01-01
  • 1970-01-01
  • 2022-10-04
  • 1970-01-01
  • 2014-10-07
相关资源
最近更新 更多