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的动作在堆栈中,“ If”宏交换它们并有条件地进行校准。然后将执行堆栈的顶部,并将未使用的宏放入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=IlExvs [[/*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,和zZ弹出ToS并输入数字(十进制)(如果是数字)或字符数(如果是字符串)。这对于检测结果的长度(用于缓冲输出)或计算字符串的长度很有用。请注意,对于数字,请Z推送整数部分和小数部分的组合长度。
X弹出ToS并在数字的小数部分中压入位数。如果ToS是字符串,则将其0推送。
要查找数字整数部分的位数,可以使用dZrX-。如果您尚未从default更改精度k==0,则使用1/Zshort会更短,但是假设您需要在操作后保持特定的非零精度: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警告,也可以用逗号分隔数字。