プリミティブ型 | メモリ内のサイズ | 値の範囲 |
---|---|---|
バイト | 8ビット | -128~127 |
短い | 16ビット | -32768 ~ 32767 |
文字 | 16ビット | 0~65536 |
整数 | 32ビット | -2147483648 ~ 2147483647 |
長さ | 64ビット | -9223372036854775808 ~ 9223372036854775807 |
浮く | 32ビット | (2 の -149 乗) ~ ((2 の -23 乗) * 2 の 127 乗) |
ダブル | 64ビット | (-2の63乗) ~ ((2の63乗) - 1) |
ブール値 | 8 (配列で使用される場合)、32 (配列で使用されない場合) | 正しいか間違っているか |
public class Main {
public static void main(String[] args) {
BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
System.out.println(integer);
BigDecimal decimal = new BigDecimal("123.444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444");
System.out.println(decimal);
}
}
コンストラクターに文字列を渡すことは、可能なオプションの 1 つにすぎません。ここでは、数値がlongとdoubleの最大値を超えているため、文字列を使用します。また、どの数値を作成するかをコンパイラーに説明する何らかの方法が必要です:) 数値 1111111111111111111111111111111111111111111111111111111111111111111111111111を渡すだけです。 11111111111111111111111111111111111111111111111111111111111111111 Java は渡された数値をプリミティブ データ型の 1 つに詰め込もうとしますが、どのデータ型にも適合しません。そのため、文字列を使用して必要な数値を渡すことが良い選択肢となります。どちらのクラスも、渡された文字列から数値を自動的に抽出できます。大きな数のクラスを扱うときに覚えておくべきもう 1 つの重要な点は、そのオブジェクトが不変 ( Immutable ) であるということです。Stringクラスとプリミティブ型 (Integer、Long など) のラッパー クラスの 経験により、不変性についてはすでによく理解されています。
import java.math.BigInteger;
public class Main {
public static void main(String[] args) {
BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
System.out.println(integer);
integer.add(BigInteger.valueOf(33333333));
System.out.println(integer);
}
}
コンソール出力:
11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
ご想像のとおり、番号は変わっていません。加算操作を実行するには、操作の結果を受け取る新しいオブジェクトを作成する必要があります。
import java.math.BigInteger;
public class Main {
public static void main(String[] args) {
BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
System.out.println(integer);
BigInteger result = integer.add(BigInteger.valueOf(33333333));
System.out.println(result);
}
}
コンソール出力:
11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111144444444
ほら、これですべてが正常に動作するようになりました :) ところで、加算演算がいかに珍しいかに気づきましたか?
BigInteger result = integer.add(BigInteger.valueOf(33333333));
これも重要なポイントです。大きな数のクラスでは + - * / 演算子は使用されません。代わりに、一連のメソッドが提供されます。主なメソッドを見てみましょう (いつものように、メソッドの完全なリストは Oracle ドキュメントで見つけることができます:こちらとこちら)。
-
算術演算のメソッド: add()、subtract()、multiply()、divide()。これらのメソッドは、それぞれ加算、減算、乗算、除算を実行するために使用されます。
-
doubleValue()、intValue()、floatValue()、longValue()などは、大きな数値を Java のプリミティブ型の 1 つに変換するために使用されます。これらの方法を使用する場合は注意してください。ビットサイズの違いを忘れないでください。
import java.math.BigInteger; public class Main { public static void main(String[] args) { BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"); long result = integer.longValue(); System.out.println(result); } }
コンソール出力:
8198552921648689607
-
min()とmax() を使用すると、 2 つの大きな数値の最小値と最大値を見つけることができます。
これらのメソッドは静的ではないことに注意してください。import java.math.BigInteger; public class Main { public static void main(String[] args) { BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"); BigInteger integer2 = new BigInteger("222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222"); System.out.println(integer.max(integer2)); } }
コンソール出力:
222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
BigDecimal の丸め動作
大きな数値の四捨五入と丸め動作の構成はそれほど単純ではないため、このトピックには別のセクションがあります。setScale()メソッドを使用して、BigDecimalの小数点以下の桁数を設定できます。たとえば、数値111.5555555555を小数点以下 3 桁にしたいとします。ただし、数値 3 を引数としてsetScale()メソッドに渡しても、目的を達成することはできません。前述したように、BigDecimal計算精度に厳しい要件がある数値を表現するためのものです。現在の形式では、番号は小数点以下 10 桁になります。そのうち 7 つを削除し、3 つだけを残しておきたいと考えています。したがって、数値 3 に加えて、丸めモードを通過する必要があります。 BigDecimal には、合計 8 つの丸めモードがあります。それは多いです!ただし、計算の精度を本当に微調整する必要がある場合は、必要なものがすべて揃っています。BigDecimalが提供する 8 つの丸めモードは次のとおりです。-
ROUND_CEILING — 切り上げ
111.5555555555 -> setScale(3, ROUND_CEILING) -> 111.556
-
ROUND_DOWN — ゼロに向かって丸めます
111.5555555555 -> setScale(3, ROUND_DOWN) -> 111.555
-
ROUND_FLOOR — 切り捨て
111.5555555555 -> setScale(3, ROUND_FLOOR) -> 111.555
-
ROUND_HALF_UP — 小数点以下の数値が 0.5 以上の場合に切り上げます。
0.55 -> setScale(1, ROUND_HALF_UP) -> 0.6 0.54 -> setScale(1, ROUND_HALF_UP) -> 0.5
-
ROUND_HALF_DOWN — 小数点以下の数値が 0.5 を超える場合に切り上げます。
0.55 -> setScale(1, ROUND_HALF_DOWN) -> 0.5 0.56 -> setScale(1, ROUND_HALF_DOWN) -> 0.6
-
ROUND_HALF_EVEN — 丸めは小数点の左側の数値に応じて異なります。左側の数値が偶数の場合、四捨五入されます。小数点左側の数値が奇数の場合は四捨五入となります。
2.5 -> setScale(0, ROUND_HALF_EVEN) -> 2
小数点以下の数字は 2 (偶数) です。数値は切り捨てられます。小数点以下の桁数は 0 にする必要があるため、結果は 2 になります。
3.5 -> setScale(0, ROUND_HALF_EVEN) -> 4
小数点の左側の数値は 3 (奇数) です。数値は切り上げられます。小数点以下の桁数は 0 にする必要があるため、結果は 4 になります。
-
ROUND_UNNECCESSARY — このモードは、丸めモードをメソッドに渡す必要があるが、数値を丸める必要がない場合に使用されます。ROUND_UNNECCESSARY モードを設定して数値を丸めようとすると、ArithmeticException がスローされます。
3.51 -> setScale(1, ROUND_UNNECCESSARY) -> ArithmeticException
-
ROUND_UP — ゼロから離れる方向に丸めます。
111.5551 -> setScale(3, ROUND_UP) -> 111.556
大きな数字を比較する
これも重要です。Java ではオブジェクトを比較するために、 equals()メソッドを使用していることを思い出してください。実装は、言語自体 (標準 Java クラスの場合) によって提供されるか、プログラマによってオーバーライドされます。ただし、 BigDecimalオブジェクトの場合、比較にequals()メソッドを使用することはお勧めできません。これは、BigDecimal.equals()メソッドが 2 つの数値の値とスケールが同じである場合にのみ true を返すためです。 DoubleクラスとBigDecimalクラスのequals()メソッドの動作を比較してみましょう。
import java.math.BigDecimal;
public class Main {
public static void main(String[] args) {
Double a = 1.5;
Double b = 1.50;
System.out.println(a.equals(b));
BigDecimal x = new BigDecimal("1.5");
BigDecimal y = new BigDecimal("1.50");
System.out.println(x.equals(y));
}
}
コンソール出力:
true
false
ご覧のとおり、BigDecimalの場合、数値 1.5 と 1.50 は等しくないことが判明しました。これはまさに、 BigDecimalクラスのquals()メソッドの実装の詳細によるものでした。2 つのBigDecimalオブジェクトをより正確に比較するには、 compareTo()メソッドを使用することをお勧めします。
import java.math.BigDecimal;
public class Main {
public static void main(String[] args) {
BigDecimal x = new BigDecimal("1.5");
BigDecimal y = new BigDecimal("1.50");
System.out.println(x.compareTo(y));
}
}
コンソール出力:
0
CompareTo ()メソッドは 0 を返しました。これは、1.5 と 1.50 が等しいことを意味します。そしてこれが私たちが期待していた結果です!:) 今日のレッスンはこれで終わりです。さあ、タスクに戻りましょう! :)
GO TO FULL VERSION