67358


環境 Java1.8,Eclipse4.8,MacOS10.13.6

Javaを使って **好きな桁数、好きな回数だけ四捨五入をして最大値を出力するプログラムが書きたい** です

問題としては以下です。

> あなたは以下のルールに従った四捨五入の処理のプログラムを作成することになりました。
>
> 1 以上の整数 A が与えられます。  
>  A の好きな桁に対して好きな順番で好きな回数だけ四捨五入をおこなって、できるだけ大きな整数を作ってください。
>
> たとえば、A = 247 に対して 4 通りの方法で四捨五入をおこなったときの結果は以下になります。
>
> 247→（10の位で四捨五入）→ 200  
>  247→（1の位で四捨五入）→ 250→（10の位で四捨五入）→300  
>  247→（100の位で四捨五入）→ 0  
>  247→（四捨五入しない）→ 247
>
> 247 をどのような方法で四捨五入しても 300 より大きい整数を作ることはできないので、答えは 300 になります。
>
> 入力される値  
>  入力は標準入力にて以下のフォーマットで与えられます。
>
> A
>
> ・1 行目には整数 A が与えられます。  
>  ・入力は合計で 1 行となり、入力値最終行の末尾に改行が１つ入ります。  
>  条件  
>  すべてのテストケースにおいて、以下の条件をみたします。
>
> ・1 ≦ A < 10^7  
>  ・A は整数
>
> 期待する出力  
>  整数 A の好きな桁を好きな順番で四捨五入して得られる最大の整数を出力してください。
>
> 最後は改行し、余計な文字、空行を含んではいけません。
>
> 入力例１  
>  入力  
>  247
>
> 出力  
>  300
>
> 入力例２  
>  入力  
>  31
>
> 出力  
>  31

やったこととしては以下です。  
コードを書きながら思考中。Math.roundとwhileを使ってうまくできないか。

[code]

    public class Main {
    
        public static void main(String[] args) {
    
            Scanner sc = new Scanner(System.in);
            int num1 = Integer.valueOf(sc.next());
    
            while (true) {
    
                double num2 = (Math.round(num1 / 100)) * 100;
    
                if (num2 > num1) {
                    continue;
                }
                System.out.println(num1);
                break;
            }
        }
    }
    
[/code]

もしわかる方がいればよろしくお願いいたします。


CC BY-SA 4.0
2020-06-05T11:24:00.490
67331
2020-06-06T09:09:46.033
2020-06-06T09:09:46.033
40231
40231
question
java
好きな桁数、好きな回数だけ四捨五入をして最大値を出力するプログラムが書きたい


現在のコードは大きく2点で解決までには遠いようです。

  * 四捨五入の方法

  * 繰り返しの打ち切り判定

順番に見ていきます。

* * *

### 四捨五入の方法

現在の式`(Math.round(num1 / 100)) *
100`は、10の位を四捨五入する結果を得ようとしたのでしょうが、`num1`は整数型ですので、これでは、四捨五入ではなく、常に切り捨てになってしまいます。

250を10の位で四捨五入する場合に`Math.round`を使う手順は、以下のようになります。

  1. 100で割って、四捨五入の対象桁を小数第一位に移動する 
[code]    250 -> 2.50

     ^       ^
    
[/code]

  2. `Math.round`で四捨五入 
[code]    2.50 -> 3

    
[/code]

  3. 100倍して元の値のスケールに戻す 
[code]    3 -> 300

    
[/code]

ところが現在のあなたの式だと、「100で割る」部分が`num1 / 100`と、整数型のままで除算を行っているので、整数除算が行われ、四捨五入になりません。

  1. 100で割って、四捨五入の対象桁を小数第一位に移動する…ことになっていない 
[code]    250 -> 2

     ^       ^
    
[/code]

出題の設定条件から、`float`では精度が足りないので、割り算の前に`double`に変換してやると良いでしょう。短い式ですが、勘違いがあった場合の修正を簡単にするために独立したメソッドにしてやると良いかもしれません。

[code]

        /**
         * 指定した桁位置で四捨五入する
         * @param value 元の値
         * @param digitScale 桁位置を示す 10^n の整数値
         * @return 四捨五入された値
         */
        private static double round(double value, double digitScale) {
            return Math.round(value/(digitScale * 10)) * (digitScale * 10);
        }
    
[/code]

(`Math.round`を使わずに整数演算を組み合わせて定義することもできますが、ここではやめておきます。)

* * *

### 繰り返しの打ち切り判定

四捨五入をどの桁で行うのかもよくわからないので、かなり好意的に不足する箇所を補って考えても、現在のあなたのコードは出題通りの結果に近づけないだろうと思われます。

  * 四捨五入すると元の値より大きくなる時、四捨五入した結果を保存せずにループを続行

(`247 -> 250 -> 300`という経過を見てもわかるよう、四捨五入した結果を再度四捨五入しないといけないはず)

  * 四捨五入しても元の値より大きくならない時、即座にその値を結果として終了してしまう

(ある桁で四捨五入して値が大きくならなくても、他の桁の四捨五入でどうなるかはわからない)

と言うわけで、

  * 1の位から初めて、10の位、100の位、1000の位…と四捨五入の桁を変更させながらループする  
(桁を表す数が現在の数より大きくなったらもう四捨五入の意味がないので終了)

  * 四捨五入すると元の値より大きくなる時、四捨五入した結果で元の値を置き換える

と言ったことが必要だろうと思われます。

ループの部分をざっくり書いてやると、こんな感じ。

[code]

            int value = num1;
            for( int digitScale = 1; digitScale <= value; digitScale *= 10 ) {
                //...
            }
    
[/code]

四捨五入さえ正しくできれば、あなたが自分で解けていたかもしれないので、一旦この辺で置いておきます。


CC BY-SA 4.0
2020-06-05T12:58:32.373
67334
2020-06-05T12:58:32.373
13972
67331
answer


以下のような形で実現できました。ありがとうございます。  
もっといい方法や書き方があればアドバイスお願いします。

[code]

    public class Main {
    
        public static void main(String[] args) {
    
            Scanner sc = new Scanner(System.in);
            double num1 = Integer.valueOf(sc.next());
            double num2 = 0;
            boolean isContinue = true;
    
            while (isContinue) {
    
                for (int digitScale = 10; digitScale <= (int) Math.pow(10, 7); digitScale *= 10) {
                    num2 = (Math.round(num1 / digitScale)) * digitScale;
                    if (num1 < num2) {
                        num1 = num2;
                        break;
                    }
                    if (digitScale == (int) Math.pow(10, 7)) {
                        System.out.println((int) num1);
                        isContinue = false;
                        break;
                    }
                }
            }
        }
    }
    
[/code]


CC BY-SA 4.0
2020-06-06T09:02:27.757
67358
2020-06-06T09:02:27.757
40231
67331
answer