我们需要为我的计算机体系结构类制作一个模拟 IEEE 浮点数除法的程序。我几乎已经完成了这项工作,但我认为看看程序在 APL 中的样子会很有趣,但据我所知,在 APL 中没有(直接的)方法来进行按位运算(按位和/或,换档等...)。如果可能,在 APL 中执行此操作的最简单方法是什么?
2 回答
在 APL 中执行此操作的干净(=您想要使用的方式)方式是:
- 将数字转换为位向量(或位矩阵或更高维 APL 值),
- 对位向量进行移位旋转等操作,以及
- 转换回数字
第 1 步和第 3 步相当简单:APL 有两个转换运算符 encode (⊤) 和 decode(⊥) 来做。位向量只是一种特殊情况;运算符使用任意基数(包括十六进制)。
例子:
⍝ convert 13 to 4-bit vector. The number of 2s is the result length
2 2 2 2 ⊥ 13
1 1 0 1
2 ⊥ 1 1 0 1 ⍝ convert back
13
APL 程序员不会写 2 2 2 2 来指示结果向量的所需长度,而是 (4⍴2)。这是因为对于更长的 ⊤ 参数(如您的情况下为 64),代码更具可读性。
负整数有点棘手,因为有不同的格式,如 1-complement 或 2-complement。⊤ 和 ⊥ 工作,但你必须要小心。
⊤ 和 ⊥ 提供了一些很酷的东西。首先,您可以一次转换多个数字:
2 2 2 2 ⊤ 1 2 3
0 0 0
0 0 0
0 1 1
1 0 1
接下来,如前所述,它们适用于其他基数,例如 16 以获得十六进制结果:
16 16 16 16 ⊤ 50000
12 3 5 0
结果是数字,因此您可能希望将其转换为字符:
'0123456789ABCDEF'[⎕IO+16 16 16 16⊤50000]
C350
最棘手的情况是浮点数(因此也是复数)。
大多数 APL 解释器都有系统功能,例如 APL68000 中的 ⎕DR 或 GNU APL 中的 27 ⎕CR。⎕DR 直接返回二进制向量,而 GNU APL 中的 27 ⎕CR 将 64 位 IEEE 浮点数转换为 64 位 2s 补码整数,然后可以按照上述说明进行转换。
将数字转换为位向量后,剩下的就很简单了:
- 用于访问各个位的索引 ([])
- 取 (↑) 和丢弃 (↓) 用于移位
- Rotate (⊖ 或 ⌽) 用于旋转位
- 用于二元运算的布尔函数 And/Or/Nand/Nor/Not (∧ ∨ ⍲ ⍱ 和 ~)。
根据您的 APL 系统,这是一种不干净的方法。一些 APL 系统有一个 []DR 系统函数,它允许以一种快速而松散的方式将变量的内容从一种数据类型转换为另一种数据类型。如果你有 Dyalog APL(可能这在 APL2000 中可以工作),试试这个:
)CLEAR
[]IO := 0 // sorry, no APL chars
[]PP := 16
a := 11 []DR 7.42 // 11 means "type number 1, boolean, 1 bit"
a
1 0 1 0 1 1 1 0 0 1 0 0 0 1 1 1 1 1 1 0 0 0 0 1 0 1 1 1 1 0 1 0 0 0 0 1 0 1 0 0 1 0 1 0 1 1 1 0 0 0 0 1 1 1 0 1 0 1 0 0 0 0 0 0
a[42]
1
a[42] := 0
645 []DR a // 645 means "type number 5, double, 64 bit"
7.388750000000003
)CLEAR
这里 []DR 完成了将浮点数转换为位向量的困难部分,然后再返回。(这可能正是您在计算机体系结构课上需要学习的东西,但它不是检查答案的好方法)
警告: 使用此技术,您可以构造不是有效浮点数的值。这可能会导致解释器、系统崩溃或留下一些可能导致以后出现问题的东西。一定要)CLEAR
经过实验。