JavaRush /Java Blog /Random-JA /JavaのBigDecimal

JavaのBigDecimal

Random-JA グループに公開済み
こんにちは!今日の講義では大数について話します。いいえ、本当に大きなものについては。 これまでに、プリミティブ データ型の値の範囲の表を複数回見てきました。次のようになります。
プリミティブ型 メモリ内のサイズ 値の範囲
バイト 8ビット -128~127
短い 16ビット ~ -32768 ~ 32767
チャー 16ビット 0から65536まで
整数 32ビット -2147483648 から 2147483647
長さ 64ビット -9223372036854775808 から 9223372036854775807
浮く 32ビット (2の-149乗)から((2-2の-23乗)*2の127乗)
ダブル 64ビット (-2 の 63 乗) から ((2 の 63 乗) - 1)
ブール値 8 (配列で使用する場合)、32 (配列以外で使用する場合) 正しいか間違っているか
整数について話している場合、最も容量の大きいデータ型はlongであり、浮動小数点数について話している場合は、double ですしかし、必要な数値が大きすぎて、 longにさえ収まらない場合はどうなるでしょうか? 可能な Long 値の範囲は非常に広いですが、それでも特定のサイズ (64 ビット) に制限されています。非常に大きな数値の重さが 100 ビットの場合、何を思いつくでしょうか? 幸いなことに、何も発明する必要はありません。Java では、このような場合のために、BigInteger (整数用) とBigDecimal (浮動小数点数用) という 2 つの特別なクラスが作成されました。彼らの特徴は何でしょうか?まず、理論的には最大サイズがありません。理論的には、無限のメモリを備えたコンピューターは存在しないためです。また、コンピューターのメモリのサイズを超える数値をプログラム内に作成した場合、当然のことながら、プログラムは動作しません。しかし、そのようなケースは考えにくいです。BigIntegerしたがって、数値の大きさは事実上無制限であると言えますBigDecimal。これらのクラスは何に使用されますか? まず第一に、非常に高い精度が要求される計算です。たとえば、計算の精度によって人命が左右されるプログラムがあります (飛行機やロケット用のソフトウェア、または医療機器用のソフトウェア)。したがって、小数点以下 150 位までが重要な役割を果たすのであれば、BigDecimalそれが最良の選択です。さらに、これらのオブジェクトは金融の世界でよく使用され、最小値に至るまでの計算の精度も非常に重要です。 オブジェクトを扱う方法BigIntegerと、BigDecimalオブジェクトについて覚えておくべき重要なことは何ですか? これらのクラスのオブジェクトは次のように作成されます。
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 つにすぎません。Here we use strings because our numbers exceed the maximum values long​​and double, and somehow we need to explain to the compiler exactly what number we want to get :) Just pass the number 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 to the constructor 1111111111111111111111111111111111111111111111111111111111111111111 will not work: Java will try to渡された数値をプリミティブ データ型の 1 つに「適合」させますが、どのタイプにも適合しません。したがって、文字列を使用して必要な数値を渡すことは良い選択肢です。どちらのクラスも、渡された文字列から数値を自動的に抽出できます。多数のクラスを扱うときに覚えておくべきもう 1 つの重要な点は、そのオブジェクトが immutable( 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);

   }
}
コンソール出力:

1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
ご想像のとおり、数字は変わっていません。加算操作を成功させるには、新しいオブジェクトを作成し、加算の結果をそれに割り当てる必要があります。
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);

   }
}
コンソール出力:

1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111144444444
これで、すべてが正常に動作するようになりました :) ところで、加算演算がどれほど特殊であるかに気づきましたか?
BigInteger result = integer.add(BigInteger.valueOf(33333333));
これも重要な点です。多数のクラスは、その操作で +-*/ 演算子を使用せず、代わりに一連のメソッドを提供します。 主なメソッドを見てみましょう (いつものように、メソッドの完全なリストは Oracle ドキュメントで見つけることができます:こちらこちら)。
  1. 算術演算を実行するメソッド: add()subtract()multiply()divide()。それぞれ加算、減算、乗算、除算の演算に使用されます。

  2. doubleValue()、、、などintValue()_ _ - 大きな数値を Java プリミティブ型に変換するために使用されます。容量の違いに注意して使用してください。floatValue()longValue()

    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
  3. 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 丸め制御

大きな数値を四捨五入して調整するのはそれほど単純ではないため、このトピックは別のセクションに含まれています。BigDecimalを使用して、数値の小数点以下の桁数を設定できますsetScale()。たとえば、数値111.5555555555の精度を小数点以下 3 桁に設定したいとします。ただし、数値 3 を引数としてメソッドに渡すことはできないためsetScale()、問題は解決されません。前述したように、BigDecimalこれらは精度を高めた計算のための数値です。現在の形式では、数値には小数点以下 10 桁があります。そのうち 7 つを破棄し、3 つだけを残しておきたいと考えています。したがって、数値 3 に加えて、丸めモードをパラメータとして渡す必要があります丸めモードは合計8 つありますBigDecimalかなりたくさん!ただし、プログラムの計算の精度を実際に微調整する必要がある場合は、これに必要なものがすべて揃っています。したがって、 で使用できる 8 つの丸めモードは次のとおりですBigDecimal
  1. ROUND_CEILING- 切り上げ

    111.5555555555 -> setScale(3, ROUND_CEILING) -> 111.556
  2. ROUND_DOWN- 排出廃棄

    111.5555555555 -> setScale(3, ROUND_DOWN) -> 111.555
  3. ROUND_FLOOR- 切り捨て

    111.5555555555 -> setScale(3, ROUND_FLOOR) -> 111.555

  4. ROUND_HALF_UP— 小数点以下の数値が .5 以上の場合は切り上げます。

    0.55 -> setScale(1, ROUND_HALF_UP) -> 0.6
    0.54 -> setScale(1, ROUND_HALF_UP) -> 0.5
  5. ROUND_HALF_DOWN— 小数点以下の数値が .5 を超える場合は切り上げます。

    0.55 -> setScale(1, ROUND_HALF_DOWN) -> 0.5
    0.56 -> setScale(1, ROUND_HALF_DOWN) -> 0.6
  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 になります。

  7. ROUND_UNNECCESSARY— 丸めモードを何らかのメソッドに渡す必要があるが、数値を丸める必要がない場合に使用されます。ROUND_UNNECCESSARY モードが設定されているときに数値を丸めようとすると、ArithmeticException がスローされます。

    3.51 -> setScale(1, ROUND_UNNECCESSARY) -> ArithmeticException
  8. ROUND_UP- 切り上げ。

    111.5551 -> setScale(3, ROUND_UP) -> 111.556

大きな数の比較

この質問も重要です。このメソッドが Java でオブジェクトを比較するために使用されることはすでに覚えていますequals()。これは、言語自体によって提供されるか (Java の組み込みクラスの場合)、プログラマによってオーバーライドされます。ただし、クラス オブジェクトの場合、BigDecimalこのメソッドをequals()比較に使用することはお勧めできません。その理由は、BigDecimal.equals()2 つの数値メソッドは、2 つの数値が同じ値とスケールを持つ場合にのみtrueを返すためです。 yメソッドと yメソッドの動作を比較してみましょう。 equals()DoubleBigDecimal
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
ご覧のとおり、c の場合の数値 1.5 と 1.50 はBigDecimal等しくないことが判明しました。equals()これはまさに、クラス内のメソッドの仕様が原因で発生しましたBigDecimal。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 に等しいことを意味します。これは私たちが期待していた結果です! :) これで今日のレッスンは終わりです。タスクに戻る時間です! :)
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION