Task

Express a number in decimal as a fixed-length string with leading zeros.



For example, the number   7.125   could be expressed as   00007.125.




[*
 * (n) (c) lpx
 * Print number n, using at least c characters.
 *
 * Different from normal, this function:
 *  1. Uses the current ibase (not the obase) to print the number.
 *  2. Prunes "0" digits from the right, so [1.500 1 lxp] prints "1.5".
 *  3. Pads "0" digits to the left, so [_1.5 6 lxp] prints "-001.5".
 *  4. Never prints a newline.
 *]sz
[
 Sc Sn          [Local n, c = from stack.]sz
 K Ss           [Local s = original scale.]sz
 [Reserve local variables D, F, I, L.]sz
 0 SD 0 SF 0 SI 0 SL
 
 [              [If n < 0:]sz
  [-]P           [Print negative sign.]sz
  lc 1 - sc      [Decrement c.]sz
  0 ln - sn      [Negate n.]sz
 ]sI 0 ln <I
 
 [* 
  * Array D[] takes digits before the radix point.
  *]sz
 0 k            [scale = 0]sz
 0 Sd           [Local d = 0]sz
 ln 1 /         [Push digits before radix point.]sz
 [              [Loop to fill D[]:]sz
  d 10 % ld :D   [D[d] = next digit.]sz
  ld 1 + sd      [Increment d.]sz
  10 /           [Remove digit.]sz
  d 0 !=L        [Loop until no digits.]sz
 ]sL d 0 !=L
 sz             [Pop digits.]sz
 
 [*
  * Array F[] takes digits after the radix point.
  *]sz
 ln ln 1 / -    [Push digits after radix point.]sz
 d X k          [scale = enough.]sz
 _1 Sf          [Local f = -1]sz
 d 1 +          [Push 1 + digits after radix point.]sz
 [              [Loop to count digits:]sz
  lf 1 + sf      [Increment f.]sz
  10 /           [Remove digit.]sz
  d 0 !=L        [Loop until no digits.]sz
 ]sL d 0 !=L
 sz             [Pop 1 + digits.]sz
 0 k            [scale = 0]sz
 10 lf ^ * 1 /  [Remove radix point from digits.]sz
 [              [Loop to prune digits:]sz
  lf 1 - sf      [Decrement f.]sz
  10 /           [Remove digit.]sz
  d 10 % 0 =L    [Loop while last digit is 0.]sz
 ]sL d 10 % 0 =L
 0 Si           [Local i = 0]sz
 [              [Loop to fill F[]:]sz
  d 10 % li :F   [F[i] = next digit.]sz
  10 /           [Remove digit.]sz
  li 1 + si      [Increment i.]sz
  lf li <L       [Loop while i < f.]sz
 ]sL lf li <L
 sz             [Pop digits.]sz
 
 lc ld -        [Push count = c - d.]sz
 [              [If f > 0:]sz
  1 lf + -       [Subtract 1 radix point + f from count.]sz
 ]sI 0 lf >I
 [              [Loop:]sz
  [0]P           [Print a padding "0".]sz
  1 -            [Decrement count.]sz
  d 0 <L         [Loop while count > 0.]sz
 ]sL d 0 <L
 sz             [Pop count.]sz
 
 [              [Local function (digit) lPx:]sz
  [              [Execute:]sz
   [*
    * Push the string that matches the digit.
    *]sz
   [[0] 2Q]sI d 0 =I  [[1] 2Q]sI d 1 =I  [[2] 2Q]sI d 2 =I  [[3] 2Q]sI d 3 =I
   [[4] 2Q]sI d 4 =I  [[5] 2Q]sI d 5 =I  [[6] 2Q]sI d 6 =I  [[7] 2Q]sI d 7 =I
   [[8] 2Q]sI d 8 =I  [[9] 2Q]sI d 9 =I  [[A] 2Q]sI d A =I  [[B] 2Q]sI d B =I
   [[C] 2Q]sI d C =I  [[D] 2Q]sI d D =I  [[E] 2Q]sI d E =I  [[F] 2Q]sI d F =I
   [?]            [Else push "?".]sz
  ]x
  P              [Print the string.]sz
  sz             [Pop the digit.]sz
 ]SP
 ld             [Push counter = d.]sz
 [              [Loop:]sz
  1 -            [Decrement counter.]sz
  d ;D lPx       [Print digit D[counter].]sz
  d 0 <L         [Loop while counter > 0.]sz
 ]sL d 0 <L
 sz             [Pop counter.]sz
 [              [If f > 0:]sz
  [.]P           [Print radix point.]sz
  lf              [Push counter = f.]sz
  [              [Loop:]sz
   1 -            [Decrement counter.]sz
   d ;F lPx       [Print digit F[counter].]sz
   d 0 <L         [Loop while counter > 0.]sz
  ]sL d 0 <L
  sz             [Pop counter.]sz
 ]sI 0 lf >I
 
 [Restore variables n, c, d, f, D, F, L, I, P.]sz
 Lnsz Lcsz Ldsz Lfsz LDsz LFsz LLsz LIsz LPsz
 Ls k           [Restore variable s. Restore original scale.]sz
]sp