IchigoJam BASIC で非負の数値を十進数で0埋め指定桁数出力する

[IchigoJam](https://ichigojam.net/) の [`PRINT`](https://fukuno.jig.jp/app/csv/ichigojam-cmd.html#PRINT) 命令では、桁数を指定して数値を出力できる [`BIN$`](https://fukuno.jig.jp/app/csv/ichigojam-cmd.html#BIN)・[`DEC$`](https://fukuno.jig.jp/app/csv/ichigojam-cmd.html#DEC)・[`HEX$`](https://fukuno.jig.jp/app/csv/ichigojam-cmd.html#HEX) を使用でき、それぞれ数値を二進数・十進数・十六進数で出力する。
ただし、数値が指定の桁数未満で表現できるとき、`BIN$` および `HEX$` は**0埋め**で出力してくれるが、`DEC$` は**空白埋め**で出力する。

```text:表示例
IchigoJam BASIC 1.4.1 by jig.jp
OK
PRINT BIN$(123,15)
000000001111011
OK
PRINT DEC$(123,5)
  123
OK
PRINT HEX$(123,4)
007B
OK
```

しかし、多倍長整数の下位を出力するときなど、0埋めの十進数で出力したいことがある。
そこで、この記事では非負整数を0埋めの十進数で出力する方法を紹介する。

:::note info
負の整数を出力したい場合は、まず符号を出力し、続いて [`ABS`](https://fukuno.jig.jp/app/csv/ichigojam-cmd.html#ABS) 関数で絶対値に変換して出力することで**ほとんどの場合**は実現できるだろう。
ただし、IchigoJam BASIC の整数の最小値である `-32768` は対応する正の値を表現できないため、この方法では失敗する。
この値への対応が必要かは、実現しようとするプログラムの仕様にもよるだろう。
今回は、負の整数への対応は扱わない。
:::

# 愚直な方法

愚直な方法としては、整数の大きさにより、足りない分のゼロを頭に出力することが考えられる。

以下のコードは、入力された非負整数を5桁で出力する。

```text
10 INPUT X
20 IF X<0 ?"ERROR":END
30 IF X<10000 ?0;
40 IF X<1000 ?0;
50 IF X<100 ?0;
60 IF X<10 ?0;
70 ?X
```

この方法で一応0埋めを実現できるが、`IF` 文が多く、行数が増えて面倒である。

# 0埋めできる書式を用いた方法

`BIN$` や `HEX$` は0埋めで数値を出力できるため、これらを用いて欲しい個数のゼロを出力できる。
ただし、桁数に `0` を指定してもゼロが1個出力されてしまい、「ゼロを0個出力」することはできないようである。

```text
10 INPUT X
20 IF X<0 ?"ERROR":END
30 IF X<10000 ?BIN$(0,1+(X<1000)+(X<100)+(X<10));
40 ?X
```

比較演算子は真のとき1、偽のとき0に評価されることを利用し、桁数を計算している。
「愚直な方法」よりは `IF` 文が少なく、改善されているように思える。
しかし、桁数を手動で計算する必要があり、面倒である。

# DEC$ の性質を利用した方法

IchigoJam BASIC の `DEC$` では、数値を普通に出力する際の桁数が指定した桁数を超える場合は、上位の数字を捨てて指定した桁数だけ下位を出力する。

:::note info
たとえば、C言語の `printf` は、これとは異なり数値の桁数が指定の桁数を超える場合でも数値全体を出力する。
:::

この性質を利用することで、0埋め十進数での指定桁数出力を実現できる。

## 4桁以下にのみ対応する実装

`9999` 以下の非負整数を4桁以下で出力する場合は、`10000` を足して5桁にし、桁数を指定して出力することで、0埋め十進数での指定桁数出力を実現できる。

```text
10 INPUT X
20 IF X<0 OR 9999<X ?"ERROR":END
30 ?DEC$(10000+X,4)
```

数値を出力する部分では、`IF` 文も桁数の計算もなくなり、かなりシンプルになった。

この例では4桁での出力だが、3桁以下での出力も `DEC$` の第2引数 (桁数) を変えるだけで実現できる。
「出力する非負整数が `9999` 以下」という条件を満たすことが変わらなければ、足す値は `10000` から変えなくてよい。

## 5桁に対応する実装

5桁を出力したい場合は、4桁の出力に加えて、最上位の数字を出力してやればよい。
最上位の数字は、出力する非負整数を `10000` で割ることで求めることが出来る。
IchigoJam BASIC で扱える数値は `32767` までなので、さらに余りをとるなどの処理は不要である。
また、4桁の部分は、`10000` で割った余りをとることで `9999` 以下の非負整数の出力に帰着する。

```text
10 INPUT X
20 IF X<0 ?"ERROR":END
30 ?X/10000;DEC$(X%10000+10000,4)
```

## 6桁以上に対応する実装

IchigoJam BASIC で扱える数値は `32767` までなので、6桁目以降の数字は全て `0` である。
よって、6桁以上で出力したい場合は、6桁目以降の `0` を「0埋めできる書式を用いた方法」を応用した方法で出力すればよい。

以下のコードは、入力された非負整数を10桁で出力する。

```text
10 INPUT X
20 IF X<0 ?"ERROR":END
30 ?BIN$(0,5);X/10000;DEC$(X%10000+10000,4)
```

桁数が固定であれば、`BIN$` などを用いずに直接 `0` の列を出力してもよい。

```text
10 INPUT X
20 IF X<0 ?"ERROR":END
30 ?"00000";X/10000;DEC$(X%10000+10000,4)
```

## まとめ

以下のコードは、入力された数値 `X` を桁数 `D` で出力する。
桁数は、1～10を用いる。

```text
10 INPUT X
20 IF X<0 ?"ERROR":END
30 FOR D=1 TO 10
40 IF D>5 ?BIN$(0,D-5);
50 IF D>=5 ?X/10000;
60 ?DEC$(X%10000+10000,(D-4)*(D<4)+4)
70 NEXT
```

60行目では、`D` が4以上のときは桁数を `4` とし、4未満のときは `4` に `D-4` を足した `D` を桁数としている。

# 結論

IchigoJam BASIC の `DEC$` が指定した桁数を超える上位の桁を出力しない性質を利用し、`10000` を足して5桁の数値にすることで、`9999` 以下の非負整数を0埋め4桁の十進数で出力できることがわかった。
任意の桁数に対応する場合は若干処理が長くなるが、4桁固定の場合は短いシンプルな処理で実現でき、多倍長整数の出力などで役立ちそうである。

※IchigoJamはjig.jpの登録商標です。