BigDecimal bằng () so với soTo ()


157

Hãy xem xét lớp kiểm tra đơn giản:

import java.math.BigDecimal;

/**
 * @author The Elite Gentleman
 *
 */
public class Main {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        BigDecimal x = new BigDecimal("1");
        BigDecimal y = new BigDecimal("1.00");
        System.out.println(x.equals(y));
        System.out.println(x.compareTo(y) == 0 ? "true": "false");
    }

}

Bạn có thể (có ý thức) nói rằng xbằng y(không phải tham chiếu đối tượng), nhưng khi bạn chạy chương trình, kết quả sau đây cho thấy:

false
true

Câu hỏi: Sự khác biệt giữa compareTo()equals()trong BigDecimalđó compareTocó thể xác định đó xlà bằng y?

PS: Tôi thấy rằng BigDecimal có một inflate()phương thức trên equals()phương thức. Những gì inflate()thực sự làm?


1
Quảng cáo inflate(): nó không phải là một phần của API công khai vì nó chỉ thao túng biểu diễn bên trong và không có hiệu ứng rõ ràng đối với "bên ngoài". Vì vậy, trừ khi bạn thực sự muốn nghiên cứu triển khai BigDecimalchuyên sâu, tôi khuyên bạn nên bỏ qua phương pháp này.
Joachim Sauer

Một lời giải thích ngắn và đoạn mã nguồn có thể được tìm thấy ở đây
xenteros

Câu trả lời:


224

Câu trả lời là trong JavaDoc của equals()phương thức :

Không giống như compareTo, phương thức này chỉ xem xét hai BigDecimalđối tượng bằng nhau nếu chúng bằng nhau về giá trị và tỷ lệ (do đó 2.0 không bằng 2,00 khi so sánh bằng phương pháp này).

Nói cách khác: equals()kiểm tra nếu BigDecimalđối tượng là chính xác như nhau trong tất cả các khía cạnh. compareTo()"chỉ" so sánh giá trị số của chúng.

Về lý do tại sao equals() hành xử theo cách này, điều này đã được trả lời trong câu hỏi SO này .


24
Đó là một phần rất khó BigDecimalnếu bạn không đọc kỹ JavaDoc. :) - Chúng tôi đã nhận được một số lỗi lạ từ điều này cho đến khi chúng tôi nhận ra sự khác biệt.
Thomas

3
Nhiều phần của API tiêu chuẩn xảy ra hành động "vô tình", khi điều trực quan sẽ không chính xác. BigDecimallà một trong những điều đó Do đó, người ta phải luôn luôn kiểm tra JavaDoc. Ít nhất một khi bạn phát hiện ra điều gì đó kỳ lạ đang diễn ra.
Joachim Sauer

7
Buồn cười. Sau khi đọc câu trả lời của bạn, tôi chỉ kiểm tra So sánh và thông báo rằng tính nhất quán với bằng "được khuyến khích mạnh mẽ (nhưng không bắt buộc)"
SJuan76

4
Tôi đã hỏi tại sao: stackoverflow.com/questions/14102083/ trên
bacar

8
@StephenC Tôi nghĩ không chính xác rằng sự không nhất quán này tồn tại.
Matt R

1

Tôi thấy rằng BigDecimal có phương thức Inflate () trên phương thức equals (). Inflate () làm gì thực sự?

Về cơ bản, inflate()các cuộc gọi BigInteger.valueOf(intCompact)nếu cần thiết, tức là nó tạo ra giá trị không được tính toán được lưu trữ dưới dạng BigIntegertừ long intCompact. Nếu bạn không cần điều đó BigIntegervà giá trị không được tính toán phù hợp với long BigDecimaldường như cố gắng tiết kiệm không gian càng lâu càng tốt.


Tôi không biết bạn đã viết gì (đặc biệt là với câu cuối cùng).
Buhake Sindi

@ The Elite Gentuity Câu cuối cùng chỉ nên nói rằng bên trong BigDecimalgiữ giá trị không được tính của nó trong một longcũng như a BigInteger. Nếu BigIntegerlà không cần thiết trong nội bộ nó không phải được tạo ra nhưng nếu nó là cần thiết (ví dụ như khi equalsgặp gỡ một tăng cao và một tổ chức phi thổi phồng BigDecimal) thổi phồng () `được sử dụng để tạo ra nó - Nói tóm lại:. inflate()Xử lý chuyển đổi nội bộ nếu cần thiết và vì nó là riêng tư, điều đó không quan trọng đối với người dùng của lớp.
Thomas

1

Tôi tin rằng câu trả lời đúng sẽ là làm cho hai số (BigDecimals), có cùng tỷ lệ, sau đó chúng ta có thể quyết định về sự bình đẳng của chúng. Chẳng hạn, hai số này có bằng nhau không?

1.00001 and 1.00002

Vâng, nó phụ thuộc vào quy mô. Trên thang điểm 5 (5 điểm thập phân), không có chúng không giống nhau. nhưng trên các số thập phân nhỏ hơn (thang 4 và thấp hơn) chúng được coi là bằng nhau. Vì vậy, tôi đề nghị làm cho tỷ lệ của hai số bằng nhau và sau đó so sánh chúng.


-10

Bạn cũng có thể so sánh với giá trị gấp đôi

BigDecimal a= new BigDecimal("1.1"); BigDecimal b =new BigDecimal("1.1");
System.out.println(a.doubleValue()==b.doubleValue());

5
Hãy tránh giải pháp này càng nhiều càng tốt. Ngay cả đôi cũng nên được so sánh với "epsilon". Không có ý nghĩa gì khi có BigDecimal và so sánh nó như nhân đôi..có khả năng rất cao là bạn sẽ tự bắn vào chân mình.
Vadim Kirilchuk

Các giá trị nhân đôi phải được so sánh bằng cách sử dụng epsillons
Bishwajit Purkaystha
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.