JavaRush /Blog Java /Random-VI /BigInteger và BigDecimal

BigInteger và BigDecimal

Xuất bản trong nhóm
Trong Java, một ứng dụng được tạo thành từ các lớp và các lớp được tạo thành từ các phương thức và biến. Các biến lần lượt được chia thành nguyên thủy và tham chiếu. BigInteger và BigDecimal - 1Có 8 loại biến trong Java và ngoại trừ booleanand char, chúng được chia thành các loại sau:
  • số nguyên: byte, short, intlong;
  • dấu phẩy động (còn gọi là số thực): floatdouble.
Trong các nhóm nhỏ này, sự khác biệt chỉ tồn tại trong phạm vi giá trị có thể chứa được (và theo đó, không gian chiếm giữ của biến đó sẽ thay đổi). Loại số nguyên lớn nhất là long, với phạm vi từ -9223372036854775808 đến 9223372036854775807. Trong số các số dấu phẩy động, double, có phạm vi từ 1,7e-308 đến 1,7e+308. Bạn có thể đọc thêm về số thực trong bài viết này . Nhưng nếu chúng ta cần lưu trữ những con số vượt quá phạm vi chấp nhận được thì sao? Trong trường hợp này, chúng ta sẽ cần BigIntegerBigDecimal.

BigInteger trong Java

Lớp Java BigIntegerđược sử dụng như một giá trị tương tự với các giá trị số nguyên có độ dài tùy ý không có giới hạn độ dài 64 bit. Hơn nữa, nó là hậu duệ của lớp Number, giống như các hàm bao tiêu chuẩn cho các kiểu số đơn giản - Integer, Long, Byte, Doublev.v. - do đó, nó có các triển khai các phương thức dẫn đến các kiểu đơn giản:
BigInteger value = new BigInteger("32145");

int intValue = value.intValue();//32145

long longValue = value.longValue();//32145

double doubleValue = value.doubleValue();//32145.0
Ngay lập tức, chúng ta thấy việc tạo một đối tượng như vậy BigIntegervới giá trị của chúng ta được chuyển cho hàm tạo nhưng ở định dạng chuỗi. Điều đáng chú ý là anh ấy có nhiều hơn một nhà thiết kế, nhưng dành cho mọi dịp. Nếu kiểu nguyên thủy không chứa toàn bộ lượng dữ liệu từ BigInteger, dữ liệu sẽ bị cắt bớt trong phạm vi của kiểu nguyên thủy đó. Nhưng đồng thời, có những điểm tương tự của các phương thức này ( intValueExact(), longValueExact()v.v.), với điểm khác biệt duy nhất là nếu loại đơn giản mà quá trình chuyển đổi đang diễn ra không phù hợp với phạm vi dữ liệu, thì ArithmeticException sẽ được ném ra .

Hằng số BigInteger

Để sử dụng nội bộ, lớp có các hằng số:
BigInteger.ZERO
BigInteger.ONE
BigInteger.TEN
Đây là những đối tượng không đổi BigIntegercó giá trị tương ứng là 0, 110.

Phương thức BigInteger

Một trong những tính năng chính của lớp này là nó có đầy đủ các phương thức thực hiện các phép toán số học tiêu chuẩn trong Java. Ví dụ:
  • phép tính tổng:

    BigInteger firstValue = new BigInteger("37995");
    BigInteger secondValue = new BigInteger("35466");
    BigInteger resultValue =  firstValue.add(secondValue);//73461
  • phép nhân nhân:

    BigInteger firstValue = new BigInteger("37995");
    BigInteger secondValue = new BigInteger("35466");
    BigInteger resultValue =  firstValue.multiply(secondValue);//1347530670
  • Thao tác tìm số dư khi chia số này cho số khác:

    BigInteger firstValue = new BigInteger("37995");
    BigInteger secondValue = new BigInteger("35466");
    BigInteger resultValue =  firstValue.remainder(secondValue);//2529
  • lấy giá trị tuyệt đối của một số (nghĩa là modulo, không dấu):

    BigInteger firstValue = new BigInteger("-37995");
    BigInteger resultValue =  firstValue.abs();//37995
Ngoài ra còn có các phương pháp cho các hoạt động phức tạp (cụ thể) hơn:
  • hoạt động với tính toán mod :

    BigInteger firstValue = new BigInteger("-34");
    BigInteger secondValue = new BigInteger("5");
    BigInteger resultValue = firstValue.mod(secondValue); //1
Có một số biến thể khác nhau của chức năng này:
  • lấy một số ngẫu nhiên và chỉ định số bit mà giá trị kết quả sẽ sử dụng:

    BigInteger firstValue = BigInteger.probablePrime(8, new Random());//211
    BigInteger secondValue = BigInteger.probablePrime(16, new Random());//42571
  • hoạt động dịch chuyển bitwise(this >> n)

    Sang trái:

    BigInteger firstValue = new BigInteger("5");
    BigInteger firstResultValue = firstValue.shiftLeft(3);//40

    Chuyển sang phải:

    BigInteger secondValue = new BigInteger("34");
    BigInteger secondResultValue = secondValue.shiftRight(2); //8
Tất nhiên, tốt hơn hết bạn nên xem danh sách đầy đủ các phương thức trong tài liệu . BigInteger và BigDecimal - 2

Số thập phân lớn trong Java

Khi chúng ta cần một số thực có độ dài tùy ý, lớp Java sẽ được sử dụng - BigDecimal. Theo quy định, nó được sử dụng để làm việc với tài chính thay vì double, vì nó cung cấp nhiều tùy chọn tùy chỉnh hơn. Like và BigInteger, BigDecimallà hậu duệ của một lớp Numbervà có các phương thức trả về giá trị của một đối tượng dưới dạng kiểu nguyên thủy cụ thể:
BigDecimal value = new BigDecimal(35563.3);

long longValue = value.longValue();//35563

double doubleValue = value.doubleValue();//35563.3
Như chúng ta có thể thấy khi giảm xuống long, chỉ còn lại phần nguyên và phần thập phân bị loại bỏ.

Hàm tạo BigDecimal

Chúng ta sẽ xem xét kỹ hơn các hàm tạo BigDecimalvì lớp có nhiều lựa chọn hơn về chúng. Có những hàm tạo cho phép bạn đặt giá trị của một đối tượng theo nhiều cách khác nhau (bằng cách truyền int, long, doubleStringthậm chí BigInteger) và có những hàm cho phép điều đó. đặt cài đặt của đối tượng đã tạo (phương thức làm tròn, số vị trí thập phân):
BigDecimal firstValue = new BigDecimal("455656.545");//455656.545
Ở đây mọi thứ đều rõ ràng, chúng tôi trực tiếp đặt giá trị và số chữ số thập phân mà chúng tôi muốn xem.
BigDecimal secondValue = new BigDecimal(3445.54);//3445.5399999999999636202119290828704833984375
Kết quả của hàm tạo này có thể khá khó dự đoán, bởi vì chúng ta đang chỉ định một kiểu double, về bản chất nó là một kiểu rất mơ hồ. Do đó, thông thường nên sử dụng trong hàm tạo String.
BigDecimal thirdValue = new BigDecimal(3445.554645675444, MathContext.DECIMAL32);//3445.555
Chúng tôi đặt double, nhưng đồng thời chúng tôi cũng đặt tham số mô tả quy tắc làm tròn (chứa số vị trí thập phân và thuật toán làm tròn).
char[] arr = new String("455656.545").toCharArray();

BigDecimal fourthValue = new BigDecimal(arr, 2, 6);//5656.5
Chúng tôi đặt một mảng các ký tự từ phần tử nào chúng tôi lấy các giá trị cho đối tượng và chúng tôi lấy bao nhiêu phần tử trong số này.
BigDecimal fifthValue = new BigDecimal(new BigInteger("44554"), 3);//44.554
Chúng tôi lấy một đối tượng đã có sẵn BigInteger, đặt số vị trí thập phân.

Phương thức thập phân lớn

Lớp này BigDecimalcũng chứa các phương thức cho các phép toán số học khác nhau, nhưng BigIntegernó không có các phương thức để làm việc với bit, như . Tuy nhiên, tính năng chính BigDecimallà tính linh hoạt khi làm việc với các số dấu phẩy động. Hãy xem xét một số kỹ thuật giúp chúng ta có khả năng làm chủ các số thực:
  • chúng tôi có được độ chính xác (số lượng):

    BigDecimal value = new BigDecimal("454334.34334");
    int result = value.precision();//11
  • đặt số chữ số thập phân và quy tắc làm tròn:

    BigDecimal firstValue = new BigDecimal(3445.544445);
    
    BigDecimal secondValue = firstValue.setScale(3,BigDecimal.ROUND_CEILING);//3445.545

    Dưới đây chúng ta sẽ xem xét kỹ hơn các hằng số để thiết lập quy tắc làm tròn.

  • chia BigDecimalcho người khác BigDecimal, đồng thời chỉ ra số chữ số thập phân cần thiết và quy tắc làm tròn:

    BigDecimal firstValue = new BigDecimal("455656.545");
    
    BigDecimal secondValue = new BigDecimal(3445.544445);
    
    BigDecimal result = firstValue.divide(secondValue, 2,RoundingMode.DOWN);//132.24
  • di chuyển dấu thập phân sang phải/trái một số vị trí nhất định:

    BigDecimal value = new BigDecimal("455656.545");
    BigDecimal firstResult = value.movePointRight (2);//45565654.5
    BigDecimal secondResult = value.movePointLeft (2);//4556.56545
  • cắt số 0 ở cuối:

    BigDecimal value = new BigDecimal("45056.5000");
    BigDecimal result = value.stripTrailingZeros();//45056.5

    Nếu chúng ta có tất cả các số 0 trong phần thực và cũng có các số 0 trong phần toàn bộ (hoặc chúng ta không có chữ số thập phân nào cả), thì:

    BigDecimal value = new BigDecimal("450000.000");
    BigDecimal result = value.stripTrailingZeros();//4.5E+5

Quy tắc làm tròn số thập phân lớn

Để đặt quy tắc làm tròn, bên trong BigDecimalchúng ta có thể thấy các hằng số đặc biệt mô tả các thuật toán làm tròn: ROUND_UP- làm tròn từ 0, làm tròn về phần thực:
BigDecimal firstValue = new BigDecimal("2.578");
BigDecimal firstResult =  firstValue.setScale(1, BigDecimal.ROUND_UP );//2.6
BigDecimal secondValue = new BigDecimal("-2.578");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_UP );//-2.5
ROUND_DOWN- làm tròn về 0, nghĩa là cắt bớt phần thực:
BigDecimal firstValue = new BigDecimal("2.578");
BigDecimal firstResult =  firstValue.setScale(1, BigDecimal.ROUND_DOWN  );//2.5
BigDecimal secondValue = new BigDecimal("-2.578");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_DOWN  );//-2.6
ROUND_CEILING- làm tròn đến vô cực dương. Nghĩa là, nếu số của chúng tôi là dương thì -> ROUND_UP, nếu âm thì ->ROUND_DOWN
BigDecimal firstValue = new BigDecimal("2.578");
BigDecimal firstResult =  firstValue.setScale(1, BigDecimal.ROUND_CEILING);//2.6
BigDecimal secondValue = new BigDecimal("-2.578");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_CEILING);//-2.5
ROUND_FLOOR- làm tròn đến âm vô cực, nghĩa là nếu số của chúng ta dương thì -> ROUND_DOWN, nếu âm thì ->ROUND_UP
BigDecimal firstValue = new BigDecimal("2.578");
BigDecimal firstResult =  firstValue.setScale(1, BigDecimal.ROUND_FLOOR);//2.5
BigDecimal secondValue = new BigDecimal("-2.578");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_FLOOR);//-2.6
Đối với giá trị đang được xem xét, chúng tôi sẽ coi số gần nhất này với vị trí thập phân bị cắt cụt là lân cận gần nhất của số đang được xem xét. Ví dụ: 2,43 sẽ gần 2,4 hơn 2,5, nhưng 2,48 sẽ gần 2,5 hơn. ROUND_HALF_DOWN- làm tròn đến “người hàng xóm gần nhất”. Nếu cả hai hàng xóm cách đều nhau với một giá trị cụ thể thì việc làm tròn về 0 sẽ được thực hiện. Ví dụ, khoảng cách đều là khi số được làm tròn là 5 và có cùng khoảng cách từ 0 đến 10):
BigDecimal firstValue = new BigDecimal("2.58");
BigDecimal firstResult =  firstValue.setScale(1, BigDecimal.ROUND_HALF_DOWN );//2.6
BigDecimal secondValue = new BigDecimal("2.55");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_HALF_DOWN );//2.5
ROUND_HALF_UP— chế độ làm tròn về phía “hàng xóm gần nhất”. Nếu cả hai hàng xóm cách đều nhau, việc làm tròn được thực hiện (đây là cách làm tròn tương tự mà chúng ta đã được dạy ở trường):
BigDecimal firstValue = new BigDecimal("2.53");
BigDecimal firstResult =  firstValue.setScale(1, BigDecimal.ROUND_HALF_UP  );//2.5
BigDecimal secondValue = new BigDecimal("2.55");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_HALF_UP  );//2.6
ROUND_HALF_EVEN— làm tròn đến “hàng xóm gần nhất” nếu cả hai hàng xóm không cách đều nhau. Trong trường hợp này, nếu số được làm tròn có số lẻ đứng trước thì số đó sẽ được làm tròn lên và nếu số đó là số chẵn thì số đó sẽ được làm tròn xuống:
BigDecimal firstValue = new BigDecimal("2222.2225");
BigDecimal secondValue = firstValue.setScale(3,BigDecimal.ROUND_HALF_EVEN );//2222.222
Chúng ta có được kết quả này vì khi làm tròn, 5 nhìn vào số 2 trước đó và thấy nó chẵn nên làm tròn xuống. Nhưng nếu:
BigDecimal firstValue = new BigDecimal("2222.22255");
BigDecimal secondValue = firstValue.setScale(3,BigDecimal.ROUND_HALF_EVEN );//2222.223
Việc làm tròn đó tăng lên vì 5 số cuối cùng nhìn vào giá trị trước đó và thấy một số lẻ. Kết quả là số được làm tròn lên thành 6, sau đó số 6 tiếp theo cũng được làm tròn. Nhưng số sáu không còn nhìn vào số ở bên trái nữa, vì số này rõ ràng là ở gần phía trên hơn và kết quả là 2 cuối cùng được tăng thêm 1. ROUND_UNNECESSARY- dùng để kiểm tra xem số đó có cần làm tròn hay không. Nghĩa là, chúng tôi kiểm tra xem số có số vị trí thập phân cần thiết hay không:
BigDecimal firstValue = new BigDecimal("2.55");
BigDecimal firstResult =  firstValue.setScale(2, BigDecimal.ROUND_UNNECESSARY);//2.55
Mọi thứ ở đây đều ổn, giá trị có hai chữ số và chúng tôi kiểm tra xem chỉ có hai chữ số sau dấu thập phân. Nhưng nếu:
BigDecimal secondValue = new BigDecimal("2.55");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_UNNECESSARY);
Sau đó, chúng tôi nhận được - ArithmeticException, vì giá trị đang được kiểm tra vượt quá số vị trí thập phân được chỉ định. Nhưng nếu chúng ta kiểm tra hai chữ số thập phân, nhưng trên thực tế có một chữ số ở đó, thì ngoại lệ sẽ không được đưa ra và các chữ số bị thiếu chỉ được bổ sung bằng số 0:
BigDecimal thirdValue = new BigDecimal("2.5");
BigDecimal thirdResult = thirdValue.setScale(3, BigDecimal.ROUND_UNNECESSARY   );//2.500
Tôi cũng muốn lưu ý rằng y BigDecimalcó các hằng số tương tự như các hằng số BigInteger ZEROONE. TENĐây là một liên kết đến tài liệu . Và cuối cùng: như bạn có thể nhận thấy, khi thực hiện các thao tác với các đối tượng BigIntegerBigDecimal, chúng ta không thay đổi cái cũ mà luôn nhận được cái mới. Điều này cho chúng ta biết rằng chúng immutable, nghĩa là không thể thay đổi sau khi được tạo, giống như String. Nói cách khác, tất cả các phương thức của chúng không thể thay đổi trạng thái bên trong của đối tượng, nhiều nhất là chúng có thể trả về một đối tượng mới với các tham số được chỉ định bởi hàm chúng ta đang sử dụng.
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION