三十二日目は試行錯誤の末に

うわーいなんだかちょっと褒められた後に宿題追加されてる!?
ってことでまた悩みつつ頑張ってみたけどnullの扱いがわからない…どうすりゃいいんだろ。


例によってものすごく長くなるので、見たい人だけ見てくだされ。

色々試してみよう

さて、まずは現在の状態だとどうなるのかを確認してみるか。現在のソースはid:regasuie:20051014を参照として、おもむろに渡されたCheckerTestを実行してみる。

○結果
「12.3」を渡したところ、「false」が返されました。「true」が返されるようにしてほしいな。
「-1」を渡したところ、「false」が返されました。「true」が返されるようにしてほしいな。
「+5」を渡したところ、「false」が返されました。「true」が返されるようにしてほしいな。
「+0.0」を渡したところ、「false」が返されました。「true」が返されるようにしてほしいな。
「-0.0」を渡したところ、「false」が返されました。「true」が返されるようにしてほしいな。
「123456」を渡したところ、「true」が返されました。「false」が返されるようにしてほしいな。

ふむふむ、おおかた予想通りの結果だな。小数点と+と-が変換できないのかエラーとなって、全角数字がごく普通に変換されてる。これを改善するには…

int ichk = Integer.parseInt(chkno);
↓
double ichk = Double.parseDouble(chkno);

よしこれで小数点のところは問題なく通るだろう。Let's Try!

○結果
「12.3」を渡したところ、「false」が返されました。「true」が返されるようにしてほしいな。
「-1」を渡したところ、「false」が返されました。「true」が返されるようにしてほしいな。
「+5」を渡したところ、「false」が返されました。「true」が返されるようにしてほしいな。
「+0.0」を渡したところ、「false」が返されました。「true」が返されるようにしてほしいな。
「-0.0」を渡したところ、「false」が返されました。「true」が返されるようにしてほしいな。

あ、あれ? 全く変わってない…あ、いや。全角数字がtrue判定だったのが改善されてる。Int型だと全角数字でも変換できて、double型だと全角数字は変換できないのかな…それにしても何でdouble型に変換できないんだろ。ソースとにらめっこ…あ。
そういえばこれ、受け取った文字列から抜き取った一文字を変換してるじゃないか。そりゃ"+"や"-"や"."をdouble型にしようとしてもエラー吐くよな…って、よく考えたら一文字ずつ変換しなくても、受け取った文字列全部そのまま変換したらいいんじゃないのかこれ…ということでこう変更してみる。

double ichk = Double.parseDouble(chkno);
↓
double ichk = Double.parseDouble(chkstr);

同時に以下の部分をコメントアウト

for(int i=0; i < chklng; i++)
{
 chkno = chkstr.substring(i,(i+1));
}

一文字ずつ確認しないなら、この繰り返しは不要だしってことでまたCheckerTestを実行。

○結果
「1.」を渡したところ、「true」が返されました。「false」が返されるようにしてほしいな。
「.2」を渡したところ、「true」が返されました。「false」が返されるようにしてほしいな。

…え、その2つだけ残るの? もしかしてdouble型だと小数点も+も-もきちんと変換されるのかな。実験実験。

double ichk = Double.parseDouble(chkstr);
↓
int ichk = Integer.parseInt(chkstr);

こう変更してからCheckerTestを実行。

○結果
「12.3」を渡したところ、「false」が返されました。「true」が返されるようにしてほしいな。
「+5」を渡したところ、「false」が返されました。「true」が返されるようにしてほしいな。
「+0.0」を渡したところ、「false」が返されました。「true」が返されるようにしてほしいな。
「-0.0」を渡したところ、「false」が返されました。「true」が返されるようにしてほしいな。
「99999999999999」を渡したところ、「false」が返されました。「true」が返されるようにしてほしいな。
「123456」を渡したところ、「true」が返されました。「false」が返されるようにしてほしいな。

おー、大体あってるっぽい。Int型だと小数点、+-、全角数字、大きい桁数を扱えないみたいだな。それをdouble型だと扱える…っと。メモメモ。
一応Long型も試してみたけど、それだと「99999999999999」についてはちゃんとtrueを返してた。float型だと…あれ、「99999999999999」もtrueを返してるってことはちゃんと変換できてる…?
doubleかfloat型だと扱えるってことでいいのかな? よくわからん…
現在のソース状態はこんなの。

public class Checker {
//正しく数字が入力されたことを判断するプログラム ver.0.003
 public static boolean isNumber(String value)
 {
	 String chkstr = value;
	 
		 try{
		   double ichk = Double.parseDouble(chkstr);
		  }
		 catch(NumberFormatException e){
		   return false;
		 }
	 return true;
 }

ものすごいシンプルになった気がする…けどこれで求める結果がほとんど出てるんだよなあ。標準APIの使い方が甘いってこういうことだったんだろうか。

小数点の判定

さて、残りは「1.」と「.2」か。これがtrue判定出るってことは…おもむろにdouble変換した直後に、変換結果を出力するように追加してみる。

○結果
1.0
「1.」を渡したところ、「true」が返されました。「false」が返されるようにしてほしいな。
0.2
「.2」を渡したところ、「true」が返されました。「false」が返されるようにしてほしいな。

やっぱり。0が無くてもあるように認識されるのか…ってことは、文字列の先頭ないし末尾に"."がある場合にfalseを戻すようにすればいいか。

public class Checker {
//正しく数字が入力されたことを判断するプログラム ver.0.004
 public static boolean isNumber(String value)
 {
	 String chkstr = value;
	 int chklng = value.length();
	 String chkno1 = value.substring(0,1);
	 String chkno2 = value.substring(chklng-1);
	 try{
	   if(chkno1.equals(".") || chkno2.equals("."))
	   {
		 return false;
	   }
	   double ichk = Double.parseDouble(chkstr);
	   }
	    catch(NumberFormatException e){
		 return false;
	    }
	 return true;
	 }
}

最初、if文のところでif(chkno1 == "." || chkno2 == ".")とか書いて何でだめなんだーと混乱したのは内緒。
これでコメントアウトしてある部分以外は完了ー! ver.も0.004にしておくことに。

nullの扱いについてはわからないまま

コメントアウトしてるところを動かしてみたところ、「" "」はちゃんとfalseを戻してるみたいだけど「""」と「null」はエラーで止まるみたいだ。
catchでStringIndexOutOfBoundsExceptionを受けてみたけど結果変わらないし、いったんお手上げ。

コメントいただきました

id:regasuie:20051014の記事にid:Horiuchi_Hさんがコメントつけてくれました。
トラックバック、迷ったけどつけさせていただきました。もしご迷惑でしたらすぐに消します)

横槍みたいで恐縮ですが、
chkno = chkstr.substring(i,(i+1));
のところ、substringメソッドを使うより charAtメソッドの方がStringクラスのインスタンスを作らない分良いと思います。
あまり本質的な問題じゃないので、どっちでも良いですけど。

それと、横槍ついでにもう一つ。
StringクラスはImmutableなので、chkstr変数は基本的に不要かと思われます。

横槍だなんてそんな、むしろコメントつけていただいてこちらこそ恐縮です。
>substringメソッドを使うよりcharAtメソッドの方がStringクラスのインスタンスを作らない分良いと思います
Stringクラスのインスタンスを作らないほうが良いということでしょうか?
ここはよくわからなかったですが…
>StringクラスはImmutableなので、chkstr変数は基本的に不要かと思われます。
(´-`)ooO(Immutableって何だろう…?)
おもむろに辞書を引いてみる。

immutable
【形】 不変の

不変…? あ。
こちらのコメントを参考に、少しいじってみました。

public class Checker {
//正しく数字が入力されたことを判断するプログラム ver.0.005
  public static boolean isNumber(String value)
  {
	 int chklng = value.length();
	 String chkno1 = value.substring(0,1);
	 String chkno2 = value.substring(chklng-1);
	 
	 try{
		 if(chkno1.equals(".") || chkno2.equals("."))
		 {
			 return false;
		 }
		 double ichk = Double.parseDouble(value);
		 }
			 catch(NumberFormatException e){
				 return false;
			 }
	 return true;
  }
}

引数として宣言してるString型のvalueという変数をそのまま使えるんですね。
一つ勉強になりました、ありがとうございます。