Math・ラッパーAPI
このレッスンを終えると、Math.round の丸め方と、parseInt と valueOf の違いを言えるようになります。
まず予測してください
次の2行は何を表示するでしょうか。
System.out.println(Math.round(2.5));
System.out.println(Math.round(-2.5));答えは 3 と -2 です。-3 ではありません。ここが Silver で何度も出るところです。
Math.round は「0.5 を足して切り捨て」
Math.round の中身は、引数に 0.5 を足してから小数点以下を切り捨てる動きです。だから正の数の 2.5 は 3 になり、負の数の -2.5 は -2.0 を足した結果から -2 になります。負の側では、絶対値が小さい方に寄ることを覚えてください。-0.5 は 0 になります。
戻り値の型も出題されます。Math.round(double) は long を返し、Math.round(float) は int を返します。int x = Math.round(2.5); は long を int に入れようとするのでコンパイルエラーです。Math.round(2.5f) なら通ります。末尾の f の有無で結果が変わる形が作れるわけです。
そのほか、Math.ceil と Math.floor は double を返します。Math.ceil(2.1) は 3.0 であって 3 ではありません。出力を答える問題では小数点以下まで書かせます。Math.abs は引数と同じ型を返します。
parseInt と valueOf
Integer.parseInt("42") は基本型の int を返します。Integer.valueOf("42") はラッパー型の Integer を返します。名前が似ていて戻り値の型が違うので、代入先の型と食い違わせてコンパイルエラーを作る問題が出ます。
どちらも、数字として読めない文字列を渡すと NumberFormatException が実行時に飛びます。これは非検査例外なので、try で囲まなくてもコンパイルは通ります。空文字列や前後の空白付きの文字列でも落ちます。ここも「コンパイルエラーか実行時例外か」を分ける定番の題材です。
valueOf はキャッシュを持っていて、-128 から 127 までは同じオブジェクトを返します。この範囲の外では別のオブジェクトになるため、== の結果が変わります。ラッパーの比較は equals で行うのが正解です。
要件
- numText を parseInt で int に、valueOf で Integer に変換する
- その2つを足した数を最初に出す
- 続けて、その2つを == で比べた結果を出す
- value を Math.round したものと、value の符号を反転させたものを Math.round したものを出す
- 最後に Math.abs(-7) を出す。5つの値をこの順にスラッシュでつないで返す
入出力例
compute("42", 2.5) → "84/true/3/-2/7"
compute("7", 1.4) → "14/true/1/-1/7"
compute("200", -0.5) → "400/true/0/1/7"