2

我有一个 shell 脚本,我用 dc(1) 做了一些计算。

我需要打印一个带有前导零的数字;我找不到使用 dc 本身执行此操作的简单直接的方法,但手册页确实提到:

Z
从堆栈中弹出一个值,计算它的位数(或字符数,如果它是一个字符串)并压入该数字。数字的位数不包括任何前导零,即使它们出现在小数点的右侧。

这意味着有一种简单直接的方法......

我知道有一种千千万万的方法可以实现这一点,而且我的脚本与其中一个一起运行得很愉快。我只是好奇 ;-)

4

3 回答 3

3

试试这个:

进入:

[lc1+dsc0nld>b]sb
[sddZdscld>bp]sa
999
12lax

输出:

000000999

进入:

3lax

输出:

999

宏结束后,原始数字留在堆栈上。使用的寄存器:(a宏),b(宏),c(计数),d(数字)。

解释:

a进行设置、调用b和打印原始号码。

  • sd- 将要输出的位数存储在寄存器中d
  • dZ- 复制原始数字并推动其位数
  • dsc- 复制该计数并将其存储在寄存器中c
  • ld>b- 从寄存器加载所需的数字d,如果它大于计数,则调用宏b
  • p- 打印原始号码

b输出零,直到计数大于所需位数

  • lc1+- 从寄存器加载计数c并增加它
  • dsc- 复制计数并将其存储回寄存器c
  • 0n- 输出不带换行符的零
  • ld>b- 从寄存器加载所需的数字d,如果它仍然大于递增的计数,则循环返回以b再次运行宏,否则它将返回给调用者(宏a

要使用任意前导字符:

[lclkZ+dsclknld>b]sb
[sksddZdscld>bp]sa
999 14 [ ] lax
           999
[abc] 12 [-] lax
---------abc

除了其他寄存器之外,它还用于k存储字符(实际上可能不止一个):

[XYZ] 6 [def] lax
defXYZ
8 [ab] lax
abababXYZ
4 [ghjikl] lax
ghijklXYZ

填充字符串是整体使用的,因此如果所需的长度数大于原始字符串的长度,但小于两个字符串的长度(或整数倍),结果可能比您要求的要长。

于 2011-03-17T17:25:15.483 回答
0

这是一个例子,虽然不优雅。这将打印出 999 和 2 个前导零。您需要复制代码以获得更多数字。

#Push number to print on stack
999

# macro to print a zero
[[0]P]sa

# Print a zero if less than 5 digits
dZ5>a

# Print a zero if less than 4 digits
dZ4>a

# Print a zero if less than 3 digits
dZ3>a

# Print a zero if less than 2 digits
dZ2>a

# Print out number
p
于 2011-03-17T09:25:42.380 回答
0

给出的解决方案适用于十进制数。对于十六进制(以及任何其他输入)基数使用。例如

c=18A; dc <<< "16i${c^^}d0r[r1+r10/d0<G]dsGx4+r-[1-[0]nlGx]sY[d0<Y]dsGxr10op"
                ^ radix    formatted length ^       ^ leading symbol

你也可以试试

   c=19;   dc <<< "10i${c^^}d0r[r1+r10/d0<G]dsGx4+r-[1-[_]nlGx]sY[d0<Y]dsGxr10op"
   c=607;  dc <<< " 8i${c^^}d0r[r1+r10/d0<G]dsGx8+r-[1-[*]nlGx]sY[d0<Y]dsGxr10op"
   c=1001; dc <<< " 2i${c^^}d0r[r1+r10/d0<G]dsGx8+r-[1-[ ]nlGx]sY[d0<Y]dsGxr10op"

G并且Y是使用的寄存器。首先计算堆栈上的位数,然后计算要打印的符号数。

c=607;  dc <<< "8i${c^^}d0r[r1+r10/d0<G]dsGx f 8+r-[1-[*]nlGx]sY f [d0<Y]dsGxr10op"
于 2020-08-09T09:34:58.703 回答