aをb乗するプログラムを作成しております。
前回の質問で回答していただいた方々のおかげでとりあえずやりたかった動作をしてくれるプログラムは完成しました。
しかしこのプログラムをもうちょっとスマートにできないかと言われ困っております。
はじめは太字の部分が下のコードのようになっており、
ラベルは好ましくないといわれ以下のようなコードになりました。
それでも首を傾げられてしまい、
フラグをつかって~みたいなことを言われました。
プログラム自体は完成していますので、あとは個人のセンスになっていくとは思うのですが、
皆様だったらこのコードをどのようにかえることができるのか気になり質問させていただきました。
簡単なコードだとは思いますが、今後の参考にさせていただきたいので、ご協力よろしくお願いいたします。
import java.util.Scanner;
public class aaa {
public static void main(String[] args){ loop:while(true){ System.out.println("数値を入力して下さい。"); Scanner scan = new Scanner(System.in); String a = scan.next(); String b = scan.next(); try{ int j = Integer.parseInt(a); int k = Integer.parseInt(b); } catch (Exception e) { System.out.println("error:半角数字で入力してください。 "); continue; } int answer = 1; for(int i = 0 ; i < Integer.valueOf(b).intValue() ; i++){ answer = answer *Integer.valueOf(a).intValue(); } System.out.print(a +"の" + b + "乗は" ); System.out.println(answer + "です。"); System.out.println("計算を続けますか?[y/n]"); **while(true){ String x = scan.next(); if(x.equals("y")){ break; } else if(x.equals("n")){ System.out.println("計算を終了しました。"); System.exit(0); } else{ System.out.println("error:yまたはnを入力してください"); } ** } } }
}
while(true){ String x = scan.next(); if(x.equals("y")){ break; } else if(x.equals("n")){ break loop; } else{ System.out.println("error:yまたはnを入力してください"); } } } System.out.println("計算を終了しました。"); }
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答11件
0
Java8では以下のようなコードも書けます。参考までに。
Java
1import java.util.Scanner; 2import java.util.concurrent.Callable; 3 4public class aaa { 5 6 static int scanInt(Scanner scan) throws Exception { 7 try { 8 return Integer.parseInt(scan.next()); 9 } 10 catch(NumberFormatException e) { 11 throw new Exception("error:半角数字で入力してください。"); 12 } 13 } 14 15 static boolean scanYesNo(Scanner scan) throws Exception { 16 switch(scan.next()) { 17 case "y": return true; 18 case "n": return false; 19 default: throw new Exception("error:yまたはnを入力してください"); 20 } 21 } 22 23 static boolean loopIfException(Callable<Boolean> func) { 24 while(true) { 25 try { 26 return func.call(); 27 } 28 catch(Exception e) { 29 System.out.println(e.getMessage()); 30 } 31 } 32 } 33 34 public static void main(String[] args) { 35 Scanner scan = new Scanner(System.in); 36 do { 37 loopIfException(() -> { 38 System.out.println("数値を入力して下さい。"); 39 int a = scanInt(scan); 40 int b = scanInt(scan); 41 int answer = (int)Math.pow(a, b); 42 System.out.println(a + "の" + b + "乗は" + answer + "です。"); 43 return true; 44 }); 45 System.out.println("計算を続けますか?[y/n]"); 46 } 47 while(loopIfException(() -> scanYesNo(scan))); 48 System.out.println("計算を終了しました。"); 49 } 50 51}
投稿2016/02/05 17:03
編集2016/02/05 17:26総合スコア2183
0
スマートの意味するところにもよりますが、
こんな感じでどうでしょうか?
java
1import java.util.Scanner; 2 3public class aaa { 4 public static void main(String[] args){ 5 try(Scanner scan = new Scanner(System.in)){ 6 while(true){ 7 try{ 8 System.out.println("数値を入力して下さい。"); 9 10 long j = Long.parseLong(scan.next()); 11 long k = Long.parseLong(scan.next()); 12 13 long answer = (long)Math.pow(j, k); 14 15 System.out.println(j +"の" + k + "乗は" + answer + "です。"); 16 System.out.println("計算を続けますか?[y/n]"); 17 18 boolean loop = true; 19 while(loop){ 20 String x = scan.next(); 21 if(x.equals("n")) { 22 System.out.println("計算を終了しました。"); 23 System.exit(0); 24 } 25 else if(x.equals("y")) loop = false; 26 else System.out.println("error:yまたはnを入力してください"); 27 } 28 } catch (NumberFormatException e) { 29 System.out.println("error:半角数字で入力してください。 "); 30 } catch (Exception e) { 31 e.printStackTrace(); 32 System.out.println("error:予期しないエラーが発生した為、終了します。 "); 33 System.exit(0); 34 } 35 } 36 } 37 } 38}
補足1
ScannerはClosableの実装クラスなので、Scannerが不要になったらClose()を呼び出す必要がある。
その為、try-with-resourcesでインスタンスを作る事で、自動的にCloseするようにしている。
java
1try(Scanner scan = new Scanner(System.in)){
補足2
入力値を直接引数として渡して、不要な変数を作らない。
変数が多くなれば、それだけコードが冗長かつ複雑化しやすくなる。
これは不要かもしれないけど、累乗計算は結果が大きな数字になりやすい為、勝手にlongに変えました。
もし、さらに大きな数字や、より正確な計算結果が必要ならBigDecimalを使用すると良い。
java
1long j = Long.parseLong(scan.next()); 2long k = Long.parseLong(scan.next());
補足3ー1
累乗を求めるメソッドは存在するので、それを使用する。
単純な計算や文字列の加工等、様々なメソッドが予め用意されているので、
先に一度はググってみると良い。
java
1long answer = (long)Math.pow(j, k);
補足3-2
for文で回して計算する場合は、変数をうまく使いまわす。
java
1for(int i = 0 ; i < k ; i++){ 2 answer *= j; 3}
補足4
int等は、文字列と一緒であれば、+演算子で組み合わせるだけで、
自動的に文字列に変換される為、下記のように変数を使いまわせる。
java
1System.out.println(j +"の" + k + "乗は" + answer + "です。");
補足5
trueで無限ループにしてbreakで抜けるでも良いし、
変数でフラグ管理しても良い。
状況によって適したものにすると良い。
java
1boolean loop = true; 2while(loop){
補足6ー1
これは可読性や好みの問題があるから、こんなやり方もある程度の認識で。
if文内の処理は、1行(1処理)だけならば、{}が無くても良い。
java
1else if(x.equals("y")) loop = false; 2else System.out.println("error:yまたはnを入力してください");
補足6-2
別なやり方としては、xがここでしか使われないのであれば、
switchに入力値を直接渡してcaseで切り分ける方法もある。
これも人によって意見が分かれるので、こんなのもある程度の認識で。
java
1switch (scan.next()) { 2 case "n" : 3 System.out.println("計算を終了しました。"); 4 System.exit(0); 5 break; 6 case "y" : loop = false; break; 7 default : System.out.println("error:yまたはnを入力してください"); 8}
Long.parseLong()に失敗した時のcatchと、
その他の例外のcatchを書き分ける事で、他の例外との差別化を図る。
あと、ループの中にあるので、continueを書かなくてもcatchを抜けるとループする。
java
1} catch (NumberFormatException e) { 2 System.out.println("error:半角数字で入力してください。 "); 3} catch (Exception e) { 4 e.printStackTrace(); 5 System.out.println("error:予期しないエラーが発生した為、終了します。 "); 6 System.exit(0); 7}
投稿2016/02/05 12:26
総合スコア25
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/02/05 15:56
0
回答ではないのですが。こういう意見もありますよという表明です。
はじめは太字の部分が下のコードのようになっており、
ラベルは好ましくないといわれ以下のようなコードになりました。それでも首を傾げられてしまい、
フラグをつかって~みたいなことを言われました。
ラベルとフラグだったらラベルのほうがスマートです。状態はできるだけ少ない方が美しいのです。
なんなら「matobaaさんがそう言ってたよ」と言っていただいてもいいです。
フラグをつかって~と言っている人の、そう主張する根拠を掘り下げてみてはいかがでしょうか。
なお、System.exit はまったくもって美しくないです。状態だけじゃなく、文脈からなにからなにまで捨てるので乱暴すぎます。
投稿2016/06/24 03:51
編集2016/06/24 04:00総合スコア2493
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
指数部が整数であれば対数計算量で実現できます。参考にCで書きます(動作未検証)。ついでに再帰で書きました。
int myPow(int a, int b)
{
int temp;
switch(b){
case 0: return 1;
case 1: return a;
default:;
}
temp = myPow(a, b / 2);
return temp * temp * (b & 1 ? a : 1);
}
投稿2016/05/21 14:52
編集2016/05/26 14:58総合スコア4830
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
次の観点で変更してみました。
main() にすべての処理を書かない (1つのメソッドの行数を少なくする)
計算部分を独立させる。(別の計算に切り替えをしやすくする)
Sysem.exit() は使用しない。
main() 部の ループを while(true){ ...} から do { } while(...) にした。
java
1import java.util.Scanner; 2 3public class Clas01 { 4 5 static Scanner scan = new Scanner(System.in); 6 7 public static void main(String[] args) { 8 do { 9 int[] nums = getNumbers(); 10 System.out.print(nums[0] + "の" + nums[1] + "乗は" + calc(nums[0], nums[1]) + "です。"); 11 } while (confirm_continue()); 12 } 13 14 // a の b 乗を計算する (b は 0 以上であること) 15 // TODO: 掛け算の回数を最適化する事。 例: 2 ^ 4 は {x = (2 * 2); x * x;} と 2 回の掛け算で計算が可能である。 16 static int calc(int a, int b) { 17 int result = 1; 18 for (int i = 0; i < b; i++) { 19 result *= a; 20 } 21 return result; 22 } 23 24 // 2 つの整数を標準入力から読み込む。 25 static int[] getNumbers() { 26 while (true) { 27 try { 28 System.out.println("数値を2つ入力して下さい。"); 29 String a = scan.next(); 30 String b = scan.next(); 31 int[] ans = { Integer.parseInt(a), Integer.parseInt(b) }; 32 return ans; 33 } catch (Exception e) { 34 System.out.println("error:半角数字で入力してください。 "); 35 } 36 } 37 } 38 39 // プログラムを続けるか終了するかを標準入力から読み込む。 40 static boolean confirm_continue() { 41 System.out.println("計算を続けますか?[y/n]"); 42 while (true) { 43 String x = scan.next(); 44 if ("y".equals(x)) { 45 return true; 46 } else if ("n".equals(x)) { 47 System.out.println("計算を終了しました。"); 48 return false; 49 } else { 50 System.out.println("error:yまたはnを入力してください"); 51 } 52 } 53 } 54 55}
投稿2016/04/04 23:50
総合スコア22324
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
まず、どういうコードがスマートか分からないと困りますよね。
いろいろな観点のスマートさがありますが、どのプログラムにも求められるのは分かりやすさです。
まず、プログラムにさせたいことを、コメントとして書いてみてください。
それに合わせてプログラムを書くと、今よりはスマートなプログラムになりますよ。
投稿2016/02/06 03:07
総合スコア70
0
一旦Stringで取り込んでその後変換というのも合理性に欠けるので…
java
1import java.util.Scanner; 2public class aaa { 3 4 public static void main(String[] args){ 5 Scanner scan = new Scanner(System.in); 6 boolean doing = true; //フラグ設定 7 while(doing){ 8 9 int a, b; 10 try{ 11 System.out.println("数値を入力して下さい。"); 12 13 //nextInt()で入力から直接intを取得(intにできない入力なら例外発生) 14 a = scan.nextInt(); 15 b = scan.nextInt(); 16 } catch (InputMismatchException e) { 17 System.out.println("error:半角数字で入力してください。 "); 18 continue; 19 } 20 21 int answer = 1; 22 23 for(int i = 0 ; i < b ; i++){ 24 answer *= a; 25 } 26 27 System.out.println(a + "の" + b + "乗は" + answer + "です。"); 28 System.out.println("計算を続けますか?[y/n]"); 29 30 boolean wait = true; //y/n入力待ちフラグ 31 while(wait){ 32 switch(scan.next()){ 33 case "n": 34 System.out.println("計算を終了しました。"); 35 doing = false; //"n"の時は一番外のループを抜けるようフラグ設定 36 case "y": 37 wait = false; //"n"の時も"y"の時もここを通る 38 break; 39 default: 40 System.out.println("error:yまたはnを入力してください"); 41 } 42 43 } 44 } 45 46 } 47}
とまあコードを頑張って修正してみましたが今ひとつスマートじゃないですね…
メソッドに切り分けたほうがスマートになりそうです。
投稿2016/02/05 15:56
総合スコア20649
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
「フラグを使って〜」の部分は、最初のループを抜けるための事でしょうか。それならば、boolean型の変数を用意して、最初のwhileの条件に使用すると良いと思います。
そして現在System.exit(0)としている部分で、そのフラグを変更します。
java
1boolean isLoop = true; 2while (isLoop) { 3.... 4 else if(x.equals("n")){ 5 System.out.println("計算を終了しました。"); 6 isLoop = false; 7 break; 8 }
また、Integer.parseIntによる数値チェックで受け取っている変数jとkを、下のfor文でも使用すると良いと思います。そうすれば次の様に書くことができます。
java
1for (int i = 0; i < k; i++) { 2 answer *= j
answer *= jは、元も文と同じ意味になります。
投稿2016/02/05 10:02
編集2016/02/05 10:05総合スコア1038
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
機能・処理順序・利用メソッドを変えずに行数、字数を減らしました。
べき乗計算はjava.util.Math#pow(double,double)で代替しました。
このサイトでの初投稿のテスト的なところもあるので、ミスがあったらすみません。
java
1import java.util.*; 2class Aaa { 3 public static void main(String[] args){ 4 while(true){ 5 Scanner scan = new Scanner(System.in); 6 System.out.println("数値を入力して下さい。"); 7 8 int a, b; 9 try{ 10 a = scan.nextInt(); 11 b = scan.nextInt(); 12 } catch (Exception e) { 13 System.err.println("error:半角数字で入力してください。 "); 14 continue; 15 } 16 17 int answer = (int)Math.pow(a * 1.0, b * 1.0); 18 19 String str = ""; 20 str += a +"の" + b + "乗は"; 21 str += answer + "です。\n"; 22 str += "計算を続けますか?[y/n]"; 23 System.out.println(str); 24 25 while(true){ 26 String x = scan.next(); 27 if(x.equals("y"))break; 28 else if(x.equals("n")){ 29 System.out.println("計算を終了しました。"); 30 return; 31 } 32 33 System.err.println("error:yまたはnを入力してください"); 34 } 35 } 36 } 37}
投稿者さんのコードに指摘をするなら、
- クラス名の先頭を大文字にしていない
- intに変換できるかどうか確かめるだけならInteger.parseInt(a);をわざわざ変数で受け取る必要がない
- Integer.parseInt(a)でint型に変換しているのに、Integer.valueOf(a).intValue()でまたint型に変換している
- breakで指定していたラベルが、breakを外した後なのに残っている(loop:while())
など。これらがスマートに見えない主な要因だと思います。
機能は変えていませんが、より攻めてみました。逆に見づらいかもしれませんが行数は少ないです。
java
1import java.util.*; 2class Pow { 3 public static void main(String[] args){ 4 while(true){ 5 Scanner scan = new Scanner(System.in); 6 String str = ""; 7 System.out.println("数値を入力して下さい。"); 8 9 try{ 10 int a = scan.nextInt(), b = scan.nextInt(); 11 str += a +"の" + b + "乗は"; 12 str += (int)Math.pow(a * 1.0, b * 1.0) + "です。\n"; 13 } catch (Exception e) { 14 System.err.println("error:半角数字で入力してください。 "); 15 continue; 16 } 17 18 str += "計算を続けますか?[y/n]"; 19 System.out.println(str); 20 21 while(true){ 22 str = scan.next(); 23 if(str.equals("y"))break; 24 else if(str.equals("n")){ 25 System.out.println("計算を終了しました。"); 26 return; 27 } 28 29 System.err.println("error:yまたはnを入力してください"); 30 } 31 } 32 } 33}
投稿2016/07/01 05:53
編集2016/07/01 06:15総合スコア868
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
aをb乗するプログラムを作成しております。
それでも首を傾げられてしまい、
フラグをつかって~みたいなことを言われました。
お題が不明確ですし
このコードって、
ロジックだけ実装するのか、
ロジックと、ロジックのテストコードを実装しているのか?
ユーザーインタフェースの御勉強をしているのか?
判らないコードになっていますよね?
⇒昔々のDOS時代のBASICで作ったコードの様に見えます。
何時、何処で、誰が、何を、どの様に、如何する、結果どうなった、どうしたい?
もしかして?
1.ユーザーインタフェースとロジックを分けて
2.クラス化して~~
3.Javadoc フォーマットの御勉強した?してない?
とか、言われませんでした?
投稿2016/04/04 22:36
編集2016/04/04 22:45総合スコア2028
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
.InputMismatchException e
を使うと全角で数字を入力した場合のエラーも拾うことができます。
Java
1import java.util.*; 2 3public class Main { 4 public static void main(String[] args) { 5 Scanner sc = new Scanner(System.in); 6 try{ 7 int a = sc.nextInt(); 8 int b = sc.nextInt(); 9 System.out.println(a + "の" + b + "乗は" + (int)Math.pow(a,b) + "です。"); 10 } 11 catch(InputMismatchException e){ 12 System.out.println("半角で数字を入力してください。"); 13 } 14 } 15}
投稿2018/05/19 08:02
退会済みユーザー
総合スコア0
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。