Answers:
假设我们要检查条件a==b
(将其保存a
并b
存储在分别命名的寄存器中)。
[ # Everything is wrapped in one big macro
[ # An inner macro for our *then* part
# <-- Stuff to execute if a==b here
2Q # Then quit the inner and outer macro
]sE # `E' is for Execution register ;)
la lb =E # if a==b, execute E
# if E is executed, it will quit the whole macro, so the rest is never reached:
# <-- Stuff to execute if a!=b here
]x # End macro; Execute
(foo)
为了浓缩起见,让我们占位:
[[(then)2Q]sE(condition)E(else)]x
可以肯定的是,这是最紧凑的if语句(在此处也有推荐)。
[[thenaction]P][[elseaction]P][r]sI 2 4 =I x sI f
是一个开始?tehn和else的动作在堆栈中,“ I
f”宏交换它们并有条件地进行校准。然后将执行堆栈的顶部,并将未使用的宏放入I中以清理堆栈。2 4
只是要比较的示例数据。或者[x]sI
,如果认为可读性更高,可以将零件移至比较中[[thenaction]P][[elseaction]P] 4 4 [r]sI =I x sI f
。将f
在例子只是应当出示达堆栈干净之后...
dc
,那就是在那里我看到OpenBSD的第一页dc
的if-then-else
结构。我认为我们需要dc
针对所有主要操作系统的所有3种口味的风扇套件... o :-) ...并且我的if-then-else
上述建议对原始提案无效,dc
因为它缺少r
命令... :-(
[[(if)2Q]si(condition)i(else)]x
-将整个内容 包装在一个宏中,并将if部分包装在另一个宏中,以便您可以2Q
在到达else部分之前从整个包装中退出。因此,如果您要在1 == 1的情况下执行操作,然后打印1否则打印2,那么它将是1[[1P2Q]si1=i2P]x
(未经测试,因为我此时此刻无法访问dc。请确保我之前在此处的答案中已经做到了这一点但找不到))
[/*else*/]sE[[/*then*/]sE]sIlalb=IlEx
vs [[/*then*/2Q]sIlalb=I/*else*/]x
-6个字节的差异。仍然未经测试::P
尽管它们令初学者感到头疼,但还是dc
提供了阵列。他们像这样工作:
value index :a # store `value' in array linked to top of stack `a', with index `index'
index ;a # push a[index] on (main) stack
通常,第一个元素的索引为0。数组在处理序列时非常有用,例如 SUDSI序列)时尤其有用,尤其是与计数器结合使用时。如果想在不破坏环境的情况下选择一个特定的元素,数组可以减少所需的数量改组(以及计数器和比较的数量)。例如,如果要将一堆数字移动到数组中,则可以编写一个使用z
(堆栈深度)或z 1-
作为索引的递归函数,存储该元素并检查是否z == 0
终止自身。
[z 1- :a z 0 !=F]dsFx # or I could just write such a function for you :)
请注意以下几点:
dc
会崩溃。dc
可能是最近更新的,并且阵列行为在崩溃方面可能已经略有变化。目前无法确认任何一个,但是我认为上次在Linux上使用它时有所不同。
Z
,X
,和z
Z
弹出ToS并输入数字(十进制)(如果是数字)或字符数(如果是字符串)。这对于检测结果的长度(用于缓冲输出)或计算字符串的长度很有用。请注意,对于数字,请Z
推送整数部分和小数部分的组合长度。
X
弹出ToS并在数字的小数部分中压入位数。如果ToS是字符串,则将其0
推送。
要查找数字整数部分的位数,可以使用dZrX-
。如果您尚未从default更改精度k==0
,则使用1/Z
short会更短,但是假设您需要在操作后保持特定的非零精度:Kr0k1/Zrk
真是令人讨厌。
z
推送堆栈中的项目数。我最喜欢的命令之一,它实际上不会弹出任何值!它可用于生成数字序列或增加计数器。zd
反复使用(例如,在宏的开头)可以让人们测试每个自然数或整数的升序计算。
z
以前曾经用过这种方式,但是我从来没有想过用它来作为柜台的工具……
位数 A
到F
可以替代用于数字10〜15。然而,它们仍必须有效地视为基部10位(假定输入基为10)在不同的地方时。换句话说,输入基数10 FF
不会代表255,它将代表(15 * 10) + 15
或165。
事实上,这适用于所有数字0
以F
任何输入基地2
来16
。因此,如果输入底数为5,26E
则将为(2 * 5^2) + (6 * 5) + 14
或94。
注意,此行为对未修改的GNU源有效。但是,正如@SophiaLechner指出的那样,基于RedHat的发行版似乎使用bc-1.06-dc_ibase.patch来更改此行为,因此将数字== ibase视为ibase - 1
,而不考虑其实际值。注意,TIO dc
似乎没有bc-1.06-dc_ibase.patch(即使它的Fedora 28 __(ツ)_ /¯)。
FF
表示99
,在输入基数5 26E
中与244
即基数10 相同74
。
dc
您正在运行 哪个版本?我在ubuntu上使用GNU dc 1.4.1,在MacOS上使用GNU dc 1.3
FFp
输出99
。那您能在MacOS版本中检查一下吗?
只是偶然发现的。生成零的另一种方法:_
。
_
是直流信号,以下数字为负数。例:
_3 # pushes -3
但是,如果我们不加数字怎么办?
_ # pushes 0...sometimes
当下划线后的下一个非空白字符不是数字时,此方法有效。如果数字跟随其后,即使在换行符之后,也将其解释为负号。
c4 5_6 # -6,5,4
c4 5_ 6 # -6,5,4
c4 5_
6 # -6,5,4 # still a negative sign since the next thing it sees is a digit
c4 5_z # 3,0,5,4 # if it's followed by a non-digit, it's a 0
c4 5_p6 # 6,0,5,4
c4 _* # 0 # 4*0=0
避免空白会带来很多挑战,并且通常很容易做到dc
。除了字符串之外,必须在空格中输入空格是在一个特定的时间,当连续推送多个数字时:1 2 3
。如果必须避免这种情况:
1[]x2[]x3[]x
。35asn
并执行它介于两者之间:1lnx2lnx3lnx
。dc: ',' (054) unimplemented
警告,也可以用逗号分隔数字。