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

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

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

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

Q&A

解決済

2回答

5578閲覧

お釣り計算のプログラムを実装したい

k499778

総合スコア599

Java

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

0グッド

0クリップ

投稿2020/04/13 14:18

編集2020/04/15 04:16

前提・実現したいこと

お釣り計算のプログラムを実装したいです。

設計としては以下です。

2桁の十進数が与えられます。1つ目はアイテムの購入価格(Purchase Price: PP)です。2つ目は顧客が支払った現金(Cash: CH)です。 現在、レジの中には以下の紙幣と硬貨があります: 'PENNY': .01, 'NICKEL': .05, 'DIME': .10, 'QUARTER': .25, 'HALF DOLLAR': .50, 'ONE': 1.00, 'TWO': 2.00, 'FIVE': 5.00, 'TEN': 10.00, 'TWENTY': 20.00, 'FIFTY': 50.00, 'ONE HUNDRED': 100.00 このプログラムの目的は、顧客にお釣りとして返すべき紙幣/硬貨を計算することです。 入力: 標準入力から行を読み込む必要があります。各行にはセミコロンで区切られた2つの数値が含まれています。1つ目は購入価格(PP)で、2つ目は顧客が支払った現金(CH)です。 出力: 入力の各行に対して、顧客に返すお釣りを出力します。CH<PPの場合、ERRORを出力します。CH== PPの場合、ZEROを出力します。その他のケースは、顧客に返すべきお釣りの金額に相当する紙幣/硬貨を出力します。なお、回答はアルファベット順にソートする必要があります。 テスト 1 テストの入力 15.94;16.00 期待される出力 NICKEL,PENNY テスト 2 テストの入力 17;16 期待される出力 ERROR テスト 3 テストの入力 35;35 期待される出力 ZERO テスト 4 テストの入力 45;50 期待される出力 FIVE

この実装を完成させる手助けをしていただけませんでしょうか?

該当のソースコード

私が途中まで実装しているコードです。
型変換やプログラムの方向性で迷いながら実装しており、アドバイスいただけたらと思います。

java

1package douteki; 2 3import java.io.BufferedReader; 4import java.io.IOException; 5import java.io.InputStreamReader; 6import java.math.BigDecimal; 7import java.nio.charset.StandardCharsets; 8 9public class Main { 10 /** 11 * Iterate through each line of input. 12 */ 13 public static void main(String[] args) throws IOException { 14 InputStreamReader reader = new InputStreamReader(System.in, StandardCharsets.UTF_8); 15 BufferedReader in = new BufferedReader(reader); 16 String line; 17 while ((line = in.readLine()) != null) { 18 String[] n = line.split(";", 0); 19 20 BigDecimal val1 = new BigDecimal(n[0]); 21 BigDecimal val2 = new BigDecimal(n[1]); 22 BigDecimal bigDecimalAnswer = val2.subtract(val1); 23 24 double[] types = getMonayCount(bigDecimalAnswer, TYPES); 25 26 System.out.println("BigDecimal : " + bigDecimalAnswer); 27 } 28 } 29 30 public static final double[] TYPES = { 31 100.00, 50.00, 20.00, 10.00, 5.00, 2.00, 1.00, 0.50, 0.25, 0.10, 0.05, 0.01 32 }; 33 34 public double[] getMonayCount(double monay, double[] types) { 35 double[] type = new double[types.length]; 36 for (int i = 0; i < types.length; i++) { 37 while (monay >= types[i]) { 38 monay -= types[i]; 39 type[i] = types[i]; 40 } 41 } 42 return type; 43 } 44} 45 46//private String getMoneyNm() { 47// BigDecimal num; 48// switch (num){ 49// case 1: 50// System.out.println("非常に不満"); 51// break; 52// case 2: 53// System.out.println("少し不満"); 54// break; 55// case 3: 56// System.out.println("どちらとも言えない"); 57// break; 58// case 4: 59// System.out.println("少し満足"); 60// break; 61// case 5: 62// System.out.println("大変満足"); 63// break; 64//} 65// return num; 66//}

追記(2020.4.15.13時)
実行環境Java10,Tomcat9,Eclipse4.8.0,MacOS High Sierra10.13.6

実行しましたが、期待値が出力されません。実行も終わりません。(Macなのでコマンドは回答者様のおっしゃっているものとちがうかもしれませんので調査中です。)

イメージ説明
イメージ説明
イメージ説明
イメージ説明

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

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

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

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

kazuma-s

2020/04/13 14:54

入力が 15.92;16.00 の場合、期待される出力は何ですか? NICKEL,PENNY,PENNY,PENNY それとも NICKEL,PENNY*3 あるいは、NICKEL,THREE PENNIES?
k499778

2020/04/13 16:21

>テスト 1 テストの入力 15.94;16.00 期待される出力 NICKEL,PENNY 記載にありますが、こちらですね!
kazuma-s

2020/04/13 16:25

15.94 ではなく 15.92 の場合はどうなるかと尋ねているんです。 硬貨の枚数は関係なく、種別だけということでしょうか?
k499778

2020/04/13 16:33

入力のパターンだけの意識で構いません。汎用的でなくていいです。
jimbe

2020/04/13 16:47

後ろに付いているコメントはいったい...
k499778

2020/04/13 17:02

switch文を使って数字と名前を一致させたくて使おうと思ってます。それ以前の部分をまずは解決してからですね
jimbe

2020/04/13 17:05

なるほど, switch 文のサンプルを待機させてあるわけですね.
k499778

2020/04/13 17:28

そうです
guest

回答2

0

紙幣/貨幣名と金額の対応は, switch で一つずつ行うよりも予め対応した状態に出来る構造を用いたほうが簡単でしょう.
BigDecimal と他の型が混在すると扱いが面倒になりますので, BigDecimal に統一してしまっても良いかと思います.
設計文の中に PP や CH という単語が出てきますので, 該当する変数はその名前にしておくと, 設計と対応させての確認がし易くなります.

java

1//package douteki; 2package teratail.q253431; 3 4import java.io.*; 5import java.math.BigDecimal; 6import java.util.*; 7 8/** 紙幣/貨幣 */ 9enum Money { 10 PENNY("0.01"), NICKEL("0.05"), DIME("0.10"), QUARTER("0.25"), HALF_DOLLAR("0.50"), 11 ONE("1.00"), TWO("2.00"), FIVE("5.00"), TEN("10.00"), TWENTY("20.00"), FIFTY("50.00"), ONE_HUNDRED("100.00"); 12 13 private BigDecimal value; 14 Money(String value) { this.value = new BigDecimal(value); } 15 BigDecimal getValue() { return value; } 16 public String toString() { return super.toString().replaceAll("_", " "); } 17 18 /** 価値の高い順の Set を返す. */ 19 static Set<Money> descendingValues() { 20 if(descValues == null) { 21 descValues = new TreeSet<>(Comparator.comparing(Money::getValue).reversed()); //大きい順 22 descValues.addAll(Arrays.asList(values())); 23 } 24 return descValues; 25 } 26 static private Set<Money> descValues = null; 27} 28 29public class Main { 30 public static void main(String[] args) throws IOException { 31 try (InputStreamReader reader = new InputStreamReader(System.in); 32 BufferedReader in = new BufferedReader(reader); ) { 33 for(String line; (line = in.readLine()) != null; ) { 34 String[] items = line.split(";", 0); 35 BigDecimal pp = new BigDecimal(items[0]); 36 BigDecimal ch = new BigDecimal(items[1]); 37 38 BigDecimal change = ch.subtract(pp); 39 40 if(change.signum() < 0) { 41 System.out.println("ERROR"); 42 } else if(change.signum() == 0) { 43 System.out.println("ZERO"); 44 } else { 45 print(prepare(change)); 46 } 47 } 48 } 49 } 50 /** change 分の紙幣/硬貨を用意 */ 51 private static Map<Money,BigDecimal> prepare(BigDecimal change) { 52 Map<Money,BigDecimal> result = new HashMap<>(); 53 for(Money m : Money.descendingValues()) { 54 if(change.compareTo(m.getValue()) >= 0) { 55 BigDecimal[] dr = change.divideAndRemainder(m.getValue()); //[0]=商,[1]=剰余 56 result.put(m, dr[0]); 57 change = dr[1]; 58 } 59 } 60 return result; 61 } 62 /** お釣りの紙幣/硬貨を表示 */ 63 private static void print(Map<Money,BigDecimal> change) { 64 Set<Money> set = new TreeSet<>(Comparator.comparing(Money::toString)); //名前順 65 set.addAll(change.keySet()); 66 int i = set.size(); 67 for(Money m : set) System.out.print(m+(--i>0?",":"")); 68 System.out.println(); 69 } 70}

投稿2020/04/13 19:10

編集2020/04/14 05:14
jimbe

総合スコア13209

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

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

k499778

2020/04/13 19:37 編集

回答ありがとうございます。 in.readLine()で処理が終わらなくなるのですが、なにか原因わかりますでしょうか?
jimbe

2020/04/14 05:09

ご提示のコードから, 標準入力を閉じるまでループする構造ですが, そのような仕様では無いのですか?
k499778

2020/04/14 13:10 編集

もちろん閉じて処理が終了するように作ります。出力されず処理も終了しません。
jimbe

2020/04/14 13:10

ということは, 「in.readLine()で処理が終わらなくなる」と言われている現象が私のイメージと異なっているようです. どのような入力でどうなるはずなのがどうなっているのか, 画面の状況等を教えて頂けますか.
k499778

2020/04/14 13:13

今手元に動作環境がないので、動作環境が整い次第すぐに返答致します。
jimbe

2020/04/14 13:34

よろしくお願いします. 念の為, ctrl-z の後に Enter してみてください.
k499778

2020/04/15 04:05

MacOS High Sierra、Eclipse4.8.0 Javaアプリケーション実行をしており、引数(プログラムの引数)「15.94;16.00」をセットしています。 画像を投稿に載っけます
k499778

2020/04/15 04:18

Macだからか、ctrl-z の後に Enter でも状況が変わりません。コマンドを調べます
jimbe

2020/04/15 04:22

勘違いされておられるようですが, このプログラムの入力は「標準入力」です. 引数ではありません. Mac を使ったことが無いので OS のコマンド入力の画面がどう出来るのか分かりませんが, Eclipse では実行後「コンソール」ウインドウで"15.92;16.00"<ENTER> と入力することで動作すると思います.
k499778

2020/04/15 05:59

お恥ずかしい。お二方ともありがとうございます。
k499778

2020/04/15 06:00

できました。ありがとうございます。 最後までお付き合いいただきありがとうございました。
jimbe

2020/04/15 06:05

よかったです. ちなみに Eclipse のコンソールウインドウは"それっぽく動作するモノ"ですので時々妙な挙動をすることがあります. (OS等環境に因るかもしれませんが.) 可能であれば OS の同様の機能(?)で実行されたほうが良いかもしれません.
k499778

2020/04/15 15:56

ありがとうございます。それも模索してみます
guest

0

ベストアンサー

元のコードを全く無視しているため回答とは言えないかもしれませんが、
テスト入力は満たすはずです。

Java

1import java.util.Scanner; 2 3public class Main { 4 public static void main(String[] args) { 5 Scanner scn = new Scanner(System.in); 6 while (scn.hasNextLine()) { 7 String s = scn.nextLine(); 8 String[] n = s.split(";"); 9 double price = Double.valueOf(n[0]); 10 double payment = Double.valueOf(n[1]); 11 double change = payment - price; 12 if (change < 0) 13 System.out.println("ERROR"); 14 else if (change == 0) 15 System.out.println("ZERO"); 16 else 17 System.out.println(currency(change)); 18 } 19 } 20 21 public static final double[] value = { 22 100.00, 50.00, 20.00, 10.00, 5.00, 2.00, 1.00, 0.50, 0.25, 0.10, 0.05, 0.01 23 }; 24 public static final String[] name = { 25 "ONE HUNDRED", "FIFTY", "TWENTY", "TEN", "FIVE", "TWO", "ONE", 26 "HALF DOLLAR", "QUARTER", "DIME", "NICKEL", "PENNY" 27 }; 28 29 public static String currency(double money) { 30 String str = "", sep = ""; 31 for (int i = 0; i < name.length; i++) 32 if (money >= value[i]) { 33 money %= value[i]; 34 str += sep + name[i]; 35 sep = ","; 36 } 37 return str; 38 } 39}

実行結果

15.94;16.00 NICKEL,PENNY 17;16 ERROR 35;35 ZERO 45;50 FIVE ^Z

double の 0.01、0.05、0.10 は誤差を含むので正しくない出力になる可能性があります。

追記
15.49;16.00
HALF DOLLAR

やはり double による誤差が出てしまいました。

正しくは、
15.49;16.00
HALF DOLLAR,PENNY

やはり BigDecimal を使うことにしました。

Java

1package douteki; 2 3import java.io.IOException; 4import java.io.InputStreamReader; 5import java.io.BufferedReader; 6import java.math.BigDecimal; 7import java.nio.charset.StandardCharsets; 8 9public class Main { 10 public static void main(String[] args) throws IOException { 11 InputStreamReader reader = new InputStreamReader(System.in, StandardCharsets.UTF_8); 12 BufferedReader in = new BufferedReader(reader); 13 String line; 14 while ((line = in.readLine()) != null) { 15 String[] n = line.split(";", 0); 16 BigDecimal val1 = new BigDecimal(n[0]); 17 BigDecimal val2 = new BigDecimal(n[1]); 18 System.out.println(getMoney(val2.subtract(val1))); 19 } 20 } 21 22 public static final BigDecimal[] types = { 23 new BigDecimal("100.00"), new BigDecimal("50.00"), 24 new BigDecimal("20.00"), new BigDecimal("10.00"), 25 new BigDecimal("5.00"), new BigDecimal("2.00"), 26 new BigDecimal("1.00"), new BigDecimal( "0.50"), 27 new BigDecimal("0.25"), new BigDecimal("0.10"), 28 new BigDecimal("0.05"), new BigDecimal("0.01") 29 }; 30 public static final String[] names = { 31 "ONE HUNDRED", "FIFTY", "TWENTY", "TEN", "FIVE", "TWO", "ONE", 32 "HALF DOLLAR", "QUARTER", "DIME", "NICKEL", "PENNY" 33 }; 34 35 public static String getMoney(BigDecimal money) { 36 if (money.signum() < 0) return "ERROR"; 37 if (money.signum() == 0) return "ZERO"; 38 String type = "", sep = ""; 39 for (int i = 0; i < types.length; i++) { 40 if (money.compareTo(types[i]) >= 0) { 41 BigDecimal[] n = money.divideAndRemainder(types[i]); 42 money = n[1]; 43 type += sep + names[i]; 44 sep = ","; 45 } 46 } 47 return type; 48 } 49}

入力は、Scanner ではなく、BufferedReader にしました。

追記
プログラムの終了の仕方が分からないそうですが、コードを見てください。

while ((line = br.readLine()) != null) {
これは、readLine() で 1行読み込んで、それを line に入れる。
line に文字列が入ったらそれは null ではないので、ループの中に入ります。
1行読み込むことが出来なかったら line には null が入り、ループを終了します。

キーボード入力で、「入力はもう無いよ。終わりだよ」ということを
プログラムに伝えるためには、Linux では Ctrl-D、
Windows では Ctrl-Z と Enter のキーを押します。

投稿2020/04/13 18:49

編集2020/04/14 13:41
kazuma-s

総合スコア8224

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

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

k499778

2020/04/13 19:06 編集

回答ありがとうございます。 お釣り計算の場合、それこそ誤差を含むためbigdecimalの方がいいのかなぁと思いましたが、その点どうでしょうか?
k499778

2020/04/13 19:37

in.readLine()で処理が終わらなくなるのですが、なにか原因わかりますでしょうか?
kazuma-s

2020/04/13 23:22

どのコードのことを言っていますか? 私の回答のコードには、in.readLine() は無くて、 scn.nextLine() で入力を行っています。
k499778

2020/04/14 13:09 編集

scn.nextLine()ですね。 scn.nextLine()で実施した際にも処理が終了せず、出力されませんでした。
k499778

2020/04/14 13:11

bigdecimalでの修正ありがとうございます
k499778

2020/04/14 13:45

追記いただきありがとうございます。 出力もctrl+Dを押すまでは出ないのでしょうか? 動作環境が今手元にないので、動作環境が整い次第試して返答させていただきます。
kazuma-s

2020/04/14 13:56

動作環境は Linux なのですか? こういうことも質問に書きましょう。 コードをよく読んでいますか? 理解していますか? while ループの中で println しているから出力は出ますよ。 Ctrl-D で while ループを抜けると main は終了です。
k499778

2020/04/15 03:59 編集

動作環境はMacです >scn.nextLine()で実施した際にも処理が終了せず、出力されませんでした。 コードを読んでいて出力されそうなのに出力されていないから聞いています。 なので単純にキーボード入力の問題ではないのかなと
kazuma-s

2020/04/15 08:37

私が不思議に思うのは、Java を学習し始めて、一度もコンソール(標準入出力)を使ったことがないということです。そんなことはあり得ないと思います。いったいどうな風に学習しているのか非常に興味があります。この課題以前にどんな課題をやったのでしょうか?
k499778

2020/04/15 16:00

そうですね。標準出力という言葉を理解できていなかったです。この動きに関しては実施したことがあります。 参考書で体系的に学んだことはありますが、基本的に実務で経験しながら学んでいることが多く、実務であまりコンソールに入力してそれに対して答えが出るようなシステムは作ってきませんでした。 標準出力という言葉とやることが紐付いていなかったです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問