17.2 数値関連クラスとそのAPI（BigDecimalクラス、NumberFormatクラス、DecimalFormatクラス、Mathクラスなど）～Java Basic編

### はじめに

#### 自己紹介

皆さん、こんにちは、Udemy講師の斉藤賢哉です。私はこれまで、25年以上に渡って企業システムの開発に携わってきました。特にアーキテクトとして、ミッションクリティカルなシステムの技術設計や、Javaフレームワーク開発などの豊富な経験を有しています。
様々なセミナーでの登壇や雑誌への技術記事寄稿の実績があり、また以下のような書籍も執筆しています。
* [「マスタリング Java EE 5」（2007年）](https://amzn.asia/d/j0txqK5)
* [「アプリケーションアーキテクチャ設計パターン」（2017年）](https://amzn.asia/d/9avaCyF)

いずれも**Java EE**（**Jakarta EE**）を中心にした企業システム開発のための書籍です。中でも [「アプリケーションアーキテクチャ設計パターン」](https://amzn.asia/d/9avaCyF)は、（Javaに限定されない）比較的普遍的なテーマを扱っており、内容的にはまだまだ陳腐化していないため、興味のある方は是非手に取っていただけると幸いです（中級者向け）。

#### Udemy講座のご紹介

この記事の内容は、私が講師を務めるUdemy講座『**Java Basic編**』の一部の範囲をカバーしたものです。『**Java Basic編**』はこちらの[**リンク**](https://www.udemy.com/course/learn-java-se-basic/?referralCode=594C958456356851C97C)から購入できます（セールス対象外のためいつも同じ価格）。また**定価の約30%OFFで購入可能なクーポン**をQiita内で定期的に発行していますので、興味のある方は、ぜひ私の他の記事をチェックしてみてください。

この講座は、以下のような皆様にお薦めします。
* Javaの言語仕様や文法を正しく理解すると同時に、現場での実践的なスキル習得を目指している方
* 新卒でIT企業に入社、またはIT部門に配属になった、新米システムエンジニアの方
* 長年IT部門で活躍されてきた中堅層の方で、学び直し（リスキル）に挑戦しようとしている方
* 今後、フリーランスエンジニアとしてのキャリアを検討している方
* 「**Chat GPT**」のエンジニアリングへの活用に興味のある方
* 「**Oracle認定Javaプログラマ**」の資格取得を目指している方
* IT企業やIT部門の教育研修部門において、新人研修やリスキルのためのオンライン教材をお探しの方

#### この記事を含むシリーズ全体像

この記事はJava SEの一部の機能・仕様を取り上げたものですが、一連のシリーズになっており、**シリーズ全体でJava SEを網羅**しています。また認定資格である「**Oracle認定Javaプログラマ**」（Silver、Gold）の範囲もカバーしています。シリーズの全体像および「Oracle認定Javaプログラマ」の範囲との対応関係については、以下を参照ください。

https://qiita.com/KenyaSaitoh/items/4711a078a851510bc4da

## 17.2 数値関連クラスとそのAPI

### チャプターの概要

このチャプターでは、ラッパークラス以外の数値関連クラスの特徴やそのAPIについて学びます。

### 17.2.1 BigDecimalクラスの特徴とAPI

#### BigDecimalクラスの特徴

java.math.BigDecimalクラスは、浮動小数点数の計算において、誤差のない正確な数値を表すためのクラスです。BigDecimalクラスは、内部的には、浮動小数点数を、任意の精度整数とスケール（小数点以下桁数）に分けて管理します。例えば数値123.4567であれば、精度整数は7、スケールは4となります。このように数値を管理することで、浮動小数点数の計算には付きものの、誤差の発生を回避します。
なおBigDecimalクラスは、java.lang.Numberクラスの子クラスのため、Numberクラスで定義されたAPIは継承されています。
またBigDecimalクラスはラッパークラスなどと同様にイミュータブルのため、フィールドの型として宣言しても「マルチスレッド環境における不正な更新」（『Java Advanced編』参照）は発生しません。

#### BigDecimalクラスのAPI全体像

ここでは、BigDecimalクラスの主要なコンストラクタとAPIの一覧を取り上げます。
まずBigDecimalクラスの主要なコンストラクタは、以下のとおりです。

* BigDecimal(int)
* BigDecimal(long)
* BigDecimal(double)
* BigDecimal(String)

これらのコンストラクタの使い分けについては、次項で説明します。
またBigDecimalクラスの主要なAPIの一覧を、以下に示します。

|API（メソッド）|説明|
|--|--|
|static BigDecimal **valueOf**(long)|指定された値を持ち、スケールが0のBigDecimalを生成して返す。|
|static BigDecimal **valueOf**(long, int)|第一引数の値を持ち、スケールが第二引数のBigDecimalを生成して返す。|
|static BigDecimal **valueOf**(double)|指定されたdouble型から「Double.toString」で表される文字列表現を使用して、BigDecimalを生成して返す。|
|BigDecimal **setScale**(int)|このBigDecimalと値が等しく、スケールが指定された値を持つBigDecimalを生成して返す。|
|BigDecimal **setScale**(int, RoundingMode)|このBigDecimalと値が等しく、スケールが第一引数の値を持つBigDecimalを生成して返す。結果は、指定したRoundingModeに従って丸められる。|
|int **precision**()|このBigDecimalの精度整数を返す。|
|int **scale**()|このBigDecimalのスケール（小数点以下桁数）を返す。|
|int **signum**()|このBigDecimalの符号値（負の場合は-1、正の場合は1、ゼロの場合は0）を返す。|
|BigDecimal **add**(BigDecimal)|このBigDecimalに指定されたBigDecimalを加算し、結果をBigDecimalで返す。|
|BigDecimal **subtract**(BigDecimal)|このBigDecimalから指定されたBigDecimalを減算し、結果をBigDecimalで返す。|
|BigDecimal **multiply**(BigDecimal)|このBigDecimalに指定されたBigDecimalを乗算し、結果をBigDecimalで返す。|
|BigDecimal **divide**(BigDecimal)|このBigDecimalを指定されたBigDecimalで除算し、結果をBigDecimalで返す。結果が無限小数になる場合は、ArithmeticException例外を送出する。|
|BigDecimal **divide**(BigDecimal, RoundingMode)|このBigDecimalを第一式数のBigDecimalで除算し、結果をBigDecimalで返す。結果は、指定したRoundingModeに従って丸められる。|
|BigDecimal **divide**(BigDecimal, int, RoundingMode)|このBigDecimalを第一式数のBigDecimalで除算し、結果を第二引数のスケールを持つBigDecimalで返す。結果は、指定したRoundingModeに従って丸められる。|
|BigDecimal **abs**()|このBigDecimalの絶対値をBigDecimalで返す。|
|BigDecimal **max**(BigDecimal)|このBigDecimalと指定されたBigDecimalのうち、大きい方を返す。|
|BigDecimal **min**(BigDecimal)|このBigDecimalと指定されたBigDecimalのうち、小さい方を返す。|
|String **toString**()|このBigDecimalを文字列化して返す。|
|boolean **equals**(Object)|このBigDecimalと指定されたオブジェクトの等価性を判定して返す。指定されたオブジェクトがBigDecimal型以外の場合は、falseを返す。|
|int **compareTo**(BigDecimal)|このBigDecimalと指定されたBigDecimalの大小関係を比較する。比較の結果、自身の方が小さい場合は負の値を、大きい場合は正の値を、等しい場合は0を、それぞれ返す。|

これらのAPIの具体的な使用方法についても、次項以降で順次説明していきます。

#### BigDecimalクラスのオブジェクト生成

BigDecimalクラスの主な目的は浮動小数点数の正確な計算を行うことにありますが、まず先に整数としてのBigDecimalオブジェクトを生成し、その後の浮動小数点計算の準備をする、というケースがあります。例えば通貨に対して為替レートを適用する処理などが、その一例です。このような場合、BigDecimalのオブジェクトは、以下のように、コンストラクタに整数を渡すことで生成します。

```java:snippet_1 (pro.kensait.java.basic.lsn_17_2_1.Main_1)
BigDecimal val = new BigDecimal(10000);
```

次に、浮動小数点数を表すBigDecimalオブジェクトを生成する方法を説明します。方法としては、以下のようなものが挙げられます。

(1)コンストラクタ`BigDecimal(String)`を使う。
(2)スタティックメソッド`valueOf(long, int)`を使う。
(3)スタティックメソッド`valueOf(double)`を使う。
(4)コンストラクタ`BigDecimal(double)`を使う

例として123.4567という、精度整数が7、スケールが4の浮動小数点数を表すBigDecimalオブジェクトを、それぞれの方法で生成します。
まず(1)の方法です。

```java:snippet_2 (pro.kensait.java.basic.lsn_17_2_1.Main_1)
BigDecimal val = new BigDecimal("123.4567");
```

このようにコンストラクタに文字列"123.4567"を渡し、BigDecimalオブジェクトを生成します。例えば数値データが文字列として外部から渡されるようなケース（ユーザー入力など）では、この方法を使用します。

次に(2)の方法です。

```java:snippet_3 (pro.kensait.java.basic.lsn_17_2_1.Main_1)
BigDecimal val = BigDecimal.valueOf(1234567, 4);
```

このようにvalueOf()メソッドの第一引数にlong型の整数、第二引数にスケールを指定することで、 BigDecimalオブジェクトを生成します。値とスケールを別々に管理するケースでは、この方法を使用します。

最後に(3)の方法です。

```java:snippet_4 (pro.kensait.java.basic.lsn_17_2_1.Main_1)
BigDecimal val = BigDecimal.valueOf(123.4567);
```

このようにvalueOf()メソッドにdouble型の値を指定することで、オブジェクトを生成します。この方法は、数値データの管理との兼ね合いから、比較的よく使用される方法ではないかと考えられます。実はこの方法は、double型の値から直接BigDecimalオブジェクトを生成しているわけではなく、ラッパークラスDoubleのtoString()メソッドにより文字列化した値からオブジェクトを生成している、という点がポイントです。
double型からのオブジェクト生成という意味では、以下のようにコンストラクタにdouble型の値を渡す方法（＝(4)の方法）でも、BigDecimalオブジェクトは生成可能です。

```java:snippet_5 (pro.kensait.java.basic.lsn_17_2_1.Main_1)
BigDecimal val = new BigDecimal(123.4567);
```

ただしこの方法は、double型の123.4567という数値の時点ですでに誤差が発生しており、生成されたBigDecimalは以下のようになります。
123.4566999999999978854248183779418468475341796875
このようにコンストラクタにdouble型を渡す方法（(4)の方法）では、意図したような浮動小数点数にはならないため、注意してください。

#### 算術演算するためのAPI

BigDecimalクラスには、加算、減算、乗算、除算といった、算術演算のためのAPIが備わっています。BigDecimalはイミュータブルなため、いずれのAPIも演算の結果を新しいBigDecimalオブジェクトとして返します。例えば加算であれば、以下のようにadd()メソッドによって行います。

```java:snippet_1 (pro.kensait.java.basic.lsn_17_2_1.Main_2)
BigDecimal val1 = BigDecimal.valueOf(123.4567);
BigDecimal val2 = BigDecimal.valueOf(90000.000009);
BigDecimal result = val1.add(val2); // 90123.456709
```

この加算処理の結果は90123.456709となり、加算結果のスケールは、加算対象の2つの数値のうち大きい方に合わせられます。

#### スケールと丸めモード

BigDecimalで表される数値は、setScale()メソッドによって、スケールを後から変更することができます。まず123.45から123.4500への変更のようにスケールを拡大する場合は、setScale()メソッドに変更後のスケールを指定します。逆に123.4567から123.456への変更のようにスケールを縮小する場合は、setScale()メソッドには、変更後のスケールと、加えて丸めモードを指定します。
丸めモードは、java.math.RoundingMode列挙型によって指定します。この列挙型には、主に以下のような列挙子が定義されています。

* CEILING   … 正の無限大に近づくように丸めるモード
* FLOOR     … 負の無限大に近づくように丸めるモード
* UP        … 0から離れるように丸めるモード
* DOWN      … 0に近づくように丸めるモード
* HALF_UP   … 4以上を切り捨て、5以上を切り上げて丸めるモード（四捨五入）
* HALF_DOWN … 5以上を切り捨て、6以上を切り上げて丸めるモード
* HALF_EVEN … 5の場合は偶数に近づけるように丸めるモード（1.5→2、6.5→6）

スケールを縮小するケースを、具体的に見ていきましょう。例えば123.4567のスケールを3に縮小し、丸めモードをHALF_UP（四捨五入）とするのであれば、以下のようになります。

```java:snippet_2 (pro.kensait.java.basic.lsn_17_2_1.Main_2)
BigDecimal val1 = BigDecimal.valueOf(123.4567);
BigDecimal val2 = val1.setScale(3, RoundingMode.HALF_UP); // 123.457
```

スケールを3に縮小するため、四捨五入は小数第4位で行います。小数第4位は7のため、小数点第3位は6から7に切り上げられ、結果は123.457になります。またスケールや丸めモードは、数値の除算を行うときにも指定可能です。
以下のコードを見てください。

```java:snippet
BigDecimal val1 = BigDecimal.valueOf(123.4567);
BigDecimal val2 = BigDecimal.valueOf(3.0);
BigDecimal result = val1.divide(val2); //【1】
```

このコードではdivide()メソッドによって123.4567を3で割っています【1】が、結果は無限小数になるため、ArithmeticException例外が発生します。そこでこのコードを以下のように修正します。

```java:snippet_3 (pro.kensait.java.basic.lsn_17_2_1.Main_2)
BigDecimal val1 = BigDecimal.valueOf(123.4567);
BigDecimal val2 = BigDecimal.valueOf(3.0);
BigDecimal result = val1.divide(val2, 5, RoundingMode.HALF_UP); // 41.15223
```

divide()メソッドには、第二引数に除算結果のスケールを、第三引数に丸めモードを、それぞれ指定することができます。ここではスケールを5にし、丸めモードを四捨五入に指定しています。このように修正すると除算をしても例外は発生せず、結果として41.15223という値を持つBigDecimalオブジェクトが得られます。

#### 数値同士を比較するためのAPI

BigDecimalクラスもラッパークラスと同じように、等価性を判定するためには`==`演算子ではなく、以下のようにequals()メソッドを使用するようにしてください。

```java:snippet
BigDecimal val1 = 10;
BigDecimal val2 = 10;
boolean flag = val1.equals(val2); // true
```

BigDecimal同士の大小関係を比較する場合も、`<`や`>`といった比較演算子ではなくcompareTo()メソッドを使用します。

### 17.2.2 数値と文字列の相互変換

#### 数値と文字列を相互変換するためのクラス

数値と文字列を相互変換するためのクラスには、以下の種類があります。

* java.text.NumberFormatクラス
* java.text.DecimalFormatクラス

このうちNumberFormatクラスは、カンマ区切り形式や通貨形式など、あらかじめ決められた形式に則って変換する場合に使用します。一方でDecimalFormatクラスは、任意の形式で変換する場合に使用します。

#### NumberFormatクラスのAPI

NumberFormatクラスは、あらかじめ決められた形式に則って、数値を文字列にフォーマッティングしたり、文字列を解析して数値化したりするためのクラスです。
NumberFormatクラスには、主に以下のようなAPIが定義されています。
|API（メソッド）|説明|
|--|--|
|static NumberFormat **getInstance**()|汎用数値フォーマットを返す。|
|static NumberFormat **getIntegerInstance**()|整数型数値フォーマットを返す。|
|static NumberFormat **getCurrencyInstance**()|通貨フォーマットを返す。|
|static NumberFormat **getPercentInstance**()|パーセントフォーマットを返す。|
|void **setCurrency**(Currency)|この数値フォーマットが使用する通貨を設定する。|
|void **setGroupingUsed**(boolean)|この数値フォーマットをグループ化（カンマ区切り）するかどうかを設定する。|
|void **setMaximumIntegerDigits**(int)|この数値フォーマットの整数部分の最大桁数を設定する。|
|void **setMinimumIntegerDigits**(int)|この数値フォーマットの整数部分の最小桁数を設定する。|
|void **setMaximumFractionDigits**(int)|この数値フォーマットの小数部分の最大桁数を設定する。|
|void **setMinimumFractionDigits**(int)|この数値フォーマットの小数部分の最小桁数を設定する。|
|String **format**(long)|この数値フォーマットに従って、指定されたlong値をフォーマッティングし、文字列として返す。|
|String **format**(double)|この数値フォーマットに従って、指定されたdouble値をフォーマッティングし、文字列として返す。|
|Number **parse**(String)|指定された文字列をこの数値フォーマットに従って解析し、数値を生成して返す。|

NumberFormatクラスのオブジェクトは、ファクトリメソッドであるget〇〇Instance()メソッドによって取得します。これらのメソッドには、ロケール情報を引数に取るオーバーロードメソッドがありますが、それらについてはレッスン21.3.3で取り上げます。生成したNumberFormatオブジェクトは、set〇〇()メソッドによって後からカスタマイズすることができます。数値をフォーマッティングし文字列にするためには、format()メソッドを使用します。また文字列を解析し数値を取得するためには、parse()メソッドを使用します。
次項からは、これらのAPIの使用方法について具体的に説明していきます。

#### NumberFormatクラスによる数値→文字列変換（フォーマッティング）

ここでは、NumberFormatクラスによって数値をフォーマッティングするための方法を説明します。
以下のコードを見てください。

```java:snippet_1 (pro.kensait.java.basic.lsn_17_2_2.Main)
NumberFormat nf1 = NumberFormat.getIntegerInstance(); //【1】
NumberFormat nf2 = NumberFormat.getCurrencyInstance(); //【2】
NumberFormat nf3 = NumberFormat.getPercentInstance(); //【3】
nf3.setMaximumFractionDigits(5); //【4】
String str1 = nf1.format(1000000); // "1,000,000"
String str2 = nf2.format(1000000); // "￥1,000,000"
String str3 = nf3.format(0.1234); // "12.34%"
```

まずフォーマッティングする形式に応じてファクトリメソッドを選択し、NumberFormatのオブジェクト生成します。ここではgetIntegerInstance()メソッドで整数型数値フォーマット用オブジェクト【1】、getCurrencyInstance()メソッドで通貨フォーマット用オブジェクト【2】、そしてgetPercentInstance()メソッドでパーセントフォーマット用のオブジェクト【3】を、それぞれ生成しています。パーセントフォーマットについては、小数部分の最大桁数のデフォルトは0桁ですが、setMaximumFractionDigits()メソッドによって5桁に設定しました【4】。
このコードを実行すると、変数str1には文字列"1,000,000"が、変数str2には文字列"¥1,000,000"が、変数str3には文字列"12.34%"が、それぞれ格納されます。

#### NumberFormatクラスによる文字列→数値変換（解析）

ここではNumberFormatクラスによって文字列を解析し、数値を生成するための方法を説明します。以下のコードを見てください。

```java:snippet_2 (pro.kensait.java.basic.lsn_17_2_2.Main)
String str = "1,000,000";
NumberFormat nf = NumberFormat.getIntegerInstance(); //【1】
try {
    Integer val = nf.parse(str).intValue(); //【2】
} catch (ParseException pe) {
    new RuntimeException(pe);
}
```

フォーマッティングする形式に応じてファクトリメソッドを選択し、NumberFormatのオブジェクト生成する【1】点は、前項と同様です。ここでは、整数型数値フォーマット用オブジェクトを生成しています。
続いて生成したNumberFormatオブジェクトのparse()メソッドに、解析対象の文字列を渡します【2】。このようにすると整数型数値フォーマットに従って文字列が解析され、整数100万を表すNumberオブジェクトが返されます。
なおparse()メソッドの呼び出しでは、指定された文字列のフォーマットが不正な場合、チェック例外であるParseExceptionが送出されるため例外ハンドリングが必要です。

#### DecimalFormatクラスのAPI

DecimalFormatクラスは、任意の「数値フォーマット」に則って、数値を文字列にフォーマッティングしたり、文字列を解析して数値化したりするためのクラスです。
DecimalFormatクラスは、まず以下のようなコンストラクタによってオブジェクトを生成します。

* DecimalFormat(String)

このとき引数には、"#,###.##"のような「数値フォーマット」を指定します。
「数値フォーマット」の記法には、以下のようなものがあります。

|||
|--|--|
|0|数値1桁を表す。その桁に数値が無い場合は"0"と見なす。|
|#|数値1桁を表す。その桁に数値が無い場合はブランク。|
|.|小数点を表す。|
|,|カンマ区切りを表す。|
|-|マイナスを表す。|
|%|数値を100倍してパーセント表示にする。|

続いてAPIです。
DecimalFormatクラスはNumberFormatクラスを親に持つため、フォーマッティングや解析のためには、NumberFormatクラスから継承された以下のようなAPIを利用します。

|API（メソッド）|説明|
|--|--|
|String **format**(long)|この数値フォーマットに従って、指定されたlong値をフォーマッティングし、文字列として返す。|
|String **format**(double)|この数値フォーマットに従って、指定されたdouble値をフォーマッティングし、文字列として返す。|
|Number **parse**(String)|指定された文字列をこの数値フォーマットに従って解析し、数値を生成して返す。|

#### DecimalFormatクラスによる数値⇔文字列変換

ここでは、DecimalFormatクラスによる数値と文字列を相互に変換するための方法を説明します。ただしほとんどのケースにおいて、数値のフォーマッティングおよび解析は、既出のNumberFormatクラスで対応が可能です。そこでDecimalFormatクラスの用途として、少し特殊なケースを取り上げます。以下のコードを見てください。

```java:snippet_3 (pro.kensait.java.basic.lsn_17_2_2.Main)
DecimalFormat df = new DecimalFormat("000000000"); //【1】
String str = df.format(12345); //【2】
try {
    Integer val = df.parse(str).intValue(); //【3】
} catch (ParseException pe) {
    new RuntimeException(pe);
}
```

まず「数値フォーマット」を指定して、DecimalFormatのオブジェクト生成します【1】。ここでは、「数値フォーマット」として"000000000"を指定していますが、これは「9桁のゼロで足りない場合はその部分をゼロで埋める」というフォーマットを表します。
続いて数値から文字列へのフォーマッティングは、DecimalFormatオブジェクトのformat()メソッドに、対象の数値を指定します【2】。この例では、文字列"000012345"が生成されます。このように、事前に桁数が固定的に決まっているデータに対して、足りない桁をゼロで埋めることを「ゼロフィル」と呼びます。
続いて生成された文字列"000012345"を解析し、数値に戻してみましょう。そのためには、DecimalFormatオブジェクトのparse()メソッドに、当該文字列を指定する【3】と、今度は数値12345が生成されます。このように、先頭のゼロを取り除くことを「ゼロサプレス」と呼びます。
ゼロフィルおよびゼロサプレスは、例えば固定長形式のデータを持つシステム（メインフレームなど）とのアプリケーション連携において、必要になるケースがあります。そのようなケースでは、DecimalFormatクラスのAPIを利用すると良いでしょう。

### 17.2.3 その他の数値関連クラスのAPI

#### Mathクラスの特徴とAPI

java.lang.Mathは、指数関数、対数関数、平方根、および三角関数といった、数値処理を行うためのAPIを持つユーティリティクラスです。
このクラスには非常に数多くのAPIが定義されていますが、その中でも比較的一般的なものを以下に示します。いずれもスタティックなメソッドです。

|API（メソッド）|説明|
|--|--|
|static int **max**(int, int)|指定された2つの数値のうち、大きい方を返す。<br>※long型、float型、double型のオーバーロードメソッドあり|
|static int **min**(int, int)|指定された2つの数値のうち、小さい方を返す。<br>※long型、float型、double型のオーバーロードメソッドあり|
|static int **abs**(int)|指定された数値の絶対値を返す。<br>※long型、float型、double型のオーバーロードメソッドあり|
|static double **random**()|0.0～1.0までのランダムな数値を返す。|
|static long **round**(double)|指定された数値を四捨五入した整数を返す。<br>※float型のオーバーロードメソッドあり|
|static double **ceil**(double)|指定された数値以上の、最も小さい整数を返す（切り上げ）。|
|static double **floor**(double)|指定された数値以下の、最も大きい整数を返す（切り捨て）。|
|static double **pow**(double, double)|第一引数を、第二引数で累乗した値を返す（指数計算）。|
|static double **sqrt**(double)|指定された数値の平方根を返す。|
|static double **toRadians**(double)|指定された角度を、相当するラジアンに変換する。|
|static double **sin**(double)|指定されたラジアンのサインを返す。|
|static double **cos**(double)|指定されたラジアンのコサインを返す。|
|static double **tan**(double)|指定されたラジアンのタンジェントを返す。|

これらのAPIの中から幾つかをピックアップし、具体的な使用方法をコードで説明します。
まず浮動小数点を切り上げて整数にするためには、ceil()メソッドを呼び出します。

```java:snippet_1 (pro.kensait.java.basic.lsn_17_2_3.Main_Math)
double val = Math.ceil(111.1); // 112.0
```

指数計算を行うためには、pow()メソッドを呼び出します。このコードでは、5の3乗が計算され125.0が得られます。

```java:snippet_2 (pro.kensait.java.basic.lsn_17_2_3.Main_Math)
double val = Math.pow(5, 3); // 125.0
```

平方根を求めるためには、sqrt()メソッドを呼び出します。このコードでは、16の平方根として4.0が得られます。

```java:snippet_3 (pro.kensait.java.basic.lsn_17_2_3.Main_Math)
double val = Math.sqrt(16); // 4.0
```

Mathクラスには三角関数のための数多くのAPIがありますが、その中からコサインを求めるためのcos()メソッドを紹介します。cos()メソッドは「ラジアン」と呼ばれる角度単位を引数にとるため、一般的な角度（0～360度）から計算する場合は、先にtoRadians()メソッドでラジアンを求める必要があります。このコードでは、60度のコサインとして0.5が得られます。

```java:snippet_4 (pro.kensait.java.basic.lsn_17_2_3.Main_Math)
double val = Math.cos(Math.toRadians(60)); // 0.5000000000000001
```

#### Randomクラスの特徴とAPI

java.util.Randomは、乱数ジェネレータを表すクラスです。
このクラスのオブジェクトは、以下のコンストラクタによって生成します。

* Random()

またこのクラスの主要なAPIを以下に示します。

|API（メソッド）|説明|
|--|--|
|void **nextBytes**(byte[])|この乱数ジェネレータからランダムなバイト列を生成し、指定された変数にセットする。|
|boolean **nextBoolean**()|この乱数ジェネレータからboolean型の乱数を返す。|
|int **nextInt**()|この乱数ジェネレータからint型の乱数を返す。|
|int **nextInt**(int)|この乱数ジェネレータから0（0含む）から、指定された数値（その数値を含まない）までの、int型の乱数を返す。|
|long **nextLong**()|この乱数ジェネレータからlong型の乱数を返す。|
|float **nextFloat**()|この乱数ジェネレータから、0.0から1.0までのfloat型の乱数を返す。|
|double **nextDouble**()|この乱数ジェネレータから、0.0から1.0までのdouble型の乱数を返す。|

これらのAPIの中でも比較的よく使われるのが、nextInt()メソッドです。以下にその具体的な使用例を示します。

```java:snippet (pro.kensait.java.basic.lsn_17_2_3.Main_Random)
Random random = new Random(); //【1】
for (int i = 0; i < 100; i++) {
    int val = random.nextInt(10) + 1; //【2】
    System.out.println(val);              
}
```

このコードではまずRandomオブジェクトを生成し【1】、ループ処理の中で生成したRandomのnextInt()メソッドを呼び出すことで【2】、1から10までの乱数を連続して発生させています。Randomオブジェクトは一度生成したら、nextInt()メソッド呼び出しにより、何度でも乱数を発生させることができます。このコードでは、nextInt()メソッドの引数に10を指定して0から9までの乱数を発生させ、それに1を加えることで、1から10までの乱数を取得しています。

### このチャプターで学んだこと

このチャプターでは、以下のことを学びました。

1.	BigDecimalクラスの特徴とAPIについて。
2.	BigDecimalクラスのスケールと丸めモードについて。
3.	数値と文字列を相互変換する方法について。
4.	MathクラスやRandomクラスの特徴とAPIについて。