dc(1) 和前导零

发布于 2024-10-24 02:44:22 字数 350 浏览 4 评论 0原文

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

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

Z
从堆栈中弹出一个值,计算位数 它有(或字符数,如果它 是一个字符串)并推动它 数字。的数字计数 数字不包括任何前导 零,即使这些看起来 小数点右侧。

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

我知道有无数种方法可以实现这一点,并且我的脚本与其中之一一起运行良好。我只是好奇;-)

I've got a shell script and I do some calculations with dc(1).

I need to have one number printed with leading zeros; I can't find an easy and straightforward way to do this with dc itself, but the manpage does mention:

Z
Pops a value off the stack, calculates the number of digits
it has (or number of characters, if it
is a string) and pushes that
number. The digit count for a
number does not include any leading
zeros
, even if those appear to the
right of the radix point.

Which sort of implies there is an easy and straightforward way ...

I know there are a zillion-and-one method of accomplishing this, and I the script is running happily with one of them. I'm just curious ;-)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

别把无礼当个性 2024-10-31 02:44:22

尝试一下:

输入:

[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

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

Give this a try:

Enter:

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

Output:

000000999

Enter:

3lax

Output:

999

The original number is left on the stack after the macro ends. Registers used: a (macro), b (macro), c (count), d (digits).

Explanation:

Macro a does the setup, calls b and prints the original number.

  • sd - store the number of digits to be output in register d
  • dZ - duplicate the original number and push the count of its digits
  • dsc - duplicate that count and store it in register c
  • ld>b - load the desired digits from register d, if it's greater than the count then call macro b
  • p - print the original number

Macro b outputs zeros until the count is greater than the number of desired digits

  • lc1+ - load the count from register c and increment it
  • dsc - duplicate the count and store it back to register c
  • 0n - output a zero without a newline
  • ld>b - load the desired digits from register d, if it's still greater than the incremented count then loop back to run macro b again, otherwise it will return to the caller (macro a)

To use an arbitrary leading character:

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

In addition to the other registers, it uses k to store the character (which could actually be more than one):

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

The fill strings are used whole so the result may be longer than you asked for if the desired length number is larger than the length of the original string, but smaller than the length of the two strings (or integer multiples).

心如荒岛 2024-10-31 02:44:22

这是一个例子,尽管不优雅。这将打印出带有 2 个前导零的 999。您需要复制更多数字的代码。

#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

Here is an example, albeit inelegant. This prints out 999 with 2 leading zeros. You'll need to duplicate the code for more digits.

#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
我做我的改变 2024-10-31 02:44:22

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

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"

GY作为寄存器。首先计算堆栈上的位数,然后计算要打印的符号数。

c=607;  dc <<< "8i${c^^}d0r[r1+r10/d0<G]dsGx f 8+r-[1-[*]nlGx]sY f [d0<Y]dsGxr10op"

The solutions given work for decimal numbers. For hex (as well as for any other input) radix use. e.g.

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

You may also try

   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 and Y are the registers used. First the number of digits is counted on the stack, then the number of symbols to be printed.

c=607;  dc <<< "8i${c^^}d0r[r1+r10/d0<G]dsGx f 8+r-[1-[*]nlGx]sY f [d0<Y]dsGxr10op"
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文