0203「整数値を位ごとに表示しよう ~応用~」

今回やりたいこと


例題

前回のプログラムを、入出力する整数値が5桁でないときでも、最小限のプログラムの書き換えで流用できるようにしなさい。


要件

  • 桁数を指定する整数型の定数 DIGIT を宣言し、それを変更するだけでさまざまな桁数に対応できるようにする



実行例1

プログラム(抜粋)
final int DIGIT = 6;
標準入力
12345
標準出力
5
4
3
2
1
0



実行例2

プログラム(抜粋)
final int DIGIT = 4;
標準入力
12
標準出力
2
1
0
0


サンプルコード

import java.util.Scanner;

public class Ex_02_03 {

	public static void main(String[] args) {
		final int DIGIT = 5;	// 入出力する桁数

		// 入力
		Scanner scan = new Scanner(System.in);
		int x = scan.nextInt();

		// 出力
		for(int i=0; i<DIGIT; i++) {
			int y = (int) Math.pow(10, i+1);
			int z = (int) Math.pow(10, i);
			int a = (x%y)/z;
			System.out.println(a);
		}
	}

}


解説

final

変数を宣言するときに final を付けることで、プログラムの中で一度だけしか値を代入できない定数として宣言することができます。

今回、DIGIT は11行目

for(int i=0; i<=DIGIT; i++) {

に一度のみ使用されているだけですが、これを

for(int i=0; i<=5; i++) {

としてしまうと、この 5 がなにを意味しているのかがわかりにくいという問題があります。
これをマジックナンバーと呼びます。かっこいい名前ですが基本的には避けるのが好ましいとされています。
定数を使用することにより、この値に名前が付いたかのようになるので、意味を理解しやすくなります。

また、機能の追加などにより複数箇所で桁数が参照されるようになった場合、桁数を変更するさいに DIGIT の値をひとつ修正するだけでよいというメリットもあります。


アルゴリズム

前回のプログラムの出力部分は以下のように書かれているため、桁数を変更するたびに println 文を修正する必要がありました。

System.out.println(x%10);
System.out.println((x%100)/10);
System.out.println((x%1000)/100);
System.out.println((x%10000)/1000);
System.out.println(x/10000);

まずは最初と最後の行を機能を変えずに書き換えてみます。

System.out.println((x%10)/1);
System.out.println((x%100)/10);
System.out.println((x%1000)/100);
System.out.println((x%10000)/1000);
System.out.println((x%100000)/10000);

なんとなく法則性がみえてきましたね。まとめると以下のように

System.out.println((x%出力する位の10倍)/出力する位)

と書けるのではないでしょうか。

ここで、出力する位の10倍を y、出力する位を z とすると

一の位を出力するとき: y=101, z=100
十の位を出力するとき: y=102, z=101
…
10nの位を出力するとき: y=10n+1, z=10n

のように一般化できますね。

10nの位を出力するときの y と z はそれぞれ

y = Math.pow(10, n+1)
z = Math.pow(10, n)

となり、出力する値を a とすると

a = (x%y)/z

となります。

あとは a を for 文などで繰り返し出力してサンプルプログラムのようになれば完成です。(適当)


応用

DIGIT を任意の整数値に変更して正しく動作するかテストしてみましょう!


予告

桁数をあらかじめ指定しているせいで空桁を0で埋めないといけないのはちょっと不格好ですよね。
もうすこしあとで、入力された整数値に応じて桁数を動的に変更できるように書いていきます。