質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.51%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

11回答

5417閲覧

このコードをスマートにしてください

kaito_fl

総合スコア38

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

2クリップ

投稿2016/02/05 09:22

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ページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答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
Stripe

総合スコア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

youki_yuuki

総合スコア25

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Stripe

2016/02/05 15:18

> 補足1 STDINをあえて閉じる必要はないのでは?
youki_yuuki

2016/02/05 15:56

はい、仰るとおり閉じる必要は無いです。 あのプログラムの内容だと、意味は無いのですが、 他の補足で紹介しているのと同じで、説明の為にあえて書いてます。 端的に言ってしまえば、 「Close()とtry-with-resourcesについての説明を書きたかった」 それだけです。 ご指摘ありがとうございます。
guest

0

回答ではないのですが。こういう意見もありますよという表明です。

はじめは太字の部分が下のコードのようになっており、
ラベルは好ましくないといわれ以下のようなコードになりました。

それでも首を傾げられてしまい、
フラグをつかって~みたいなことを言われました。

ラベルとフラグだったらラベルのほうがスマートです。状態はできるだけ少ない方が美しいのです。
なんなら「matobaaさんがそう言ってたよ」と言っていただいてもいいです。

フラグをつかって~と言っている人の、そう主張する根拠を掘り下げてみてはいかがでしょうか。

なお、System.exit はまったくもって美しくないです。状態だけじゃなく、文脈からなにからなにまで捨てるので乱暴すぎます。

投稿2016/06/24 03:51

編集2016/06/24 04:00
matobaa

総合スコア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
HogeAnimalLover

総合スコア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

katoy

総合スコア22322

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

まず、どういうコードがスマートか分からないと困りますよね。
いろいろな観点のスマートさがありますが、どのプログラムにも求められるのは分かりやすさです。

まず、プログラムにさせたいことを、コメントとして書いてみてください。
それに合わせてプログラムを書くと、今よりはスマートなプログラムになりますよ。

投稿2016/02/06 03:07

wata

総合スコア70

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kaito_fl

2016/02/08 01:27

コメントはあえて書かないように指示されているため今回は省いております。 確かにコメントがあったほうがわかりやすいですよね。 つい普段からコメントを省いてしまうことが多いのでなるべく書き込むよう改善したいと思います。 ご回答ありがとうございました。
ozwk

2016/02/08 03:36

横からですが、 「何をするかを予め書いたコメントに合わせるようにコードを書く」のと 「書いたコードに何をしているかのコメントを書く」のは違うと思いますよ。
guest

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

swordone

総合スコア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
shanxia

総合スコア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
intelf___

総合スコア868

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

aをb乗するプログラムを作成しております。
それでも首を傾げられてしまい、
フラグをつかって~みたいなことを言われました。

お題が不明確ですし
このコードって、
ロジックだけ実装するのか、
ロジックと、ロジックのテストコードを実装しているのか?
ユーザーインタフェースの御勉強をしているのか?
判らないコードになっていますよね?
⇒昔々のDOS時代のBASICで作ったコードの様に見えます。
何時、何処で、誰が、何を、どの様に、如何する、結果どうなった、どうしたい?
もしかして?
1.ユーザーインタフェースとロジックを分けて
2.クラス化して~~
3.Javadoc フォーマットの御勉強した?してない?
とか、言われませんでした?

投稿2016/04/04 22:36

編集2016/04/04 22:45
daive

総合スコア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

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.51%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問