BigDecimal เท่ากับ () และ CompareTo ()


157

พิจารณาคลาสทดสอบอย่างง่าย:

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");
    }

}

คุณสามารถ (รู้ตัว) ว่านั่นxเท่ากับy(ไม่ใช่การอ้างอิงวัตถุ) แต่เมื่อคุณรันโปรแกรมผลลัพธ์ต่อไปนี้จะแสดง:

false
true

คำถาม: อะไรคือความแตกต่างระหว่างcompareTo()และequals()ในBigDecimalสิ่งที่compareToสามารถตัดสินได้ว่าxเท่ากับy?

PS: ฉันเห็นว่า BigDecimal มีinflate()วิธีการเกี่ยวกับequals()วิธีการ อะไรinflate()ทำจริง?


1
โฆษณาinflate(): มันไม่ได้เป็นส่วนหนึ่งของ API สาธารณะเพราะเป็นเพียงการจัดการการแสดงภายในและไม่มีผลต่อ "นอก" ดังนั้นหากคุณไม่ต้องการศึกษาการใช้งานBigDecimalเชิงลึกอย่างแท้จริงฉันขอแนะนำให้คุณละเว้นวิธีนี้
Joachim Sauer

คำอธิบายสั้น ๆ และตัวอย่างซอร์สโค้ดสามารถพบได้ที่นี่
xenteros

คำตอบ:


224

คำตอบอยู่ในJavaDoc ของequals()วิธีการ :

แตกต่างจากcompareToวิธีนี้พิจารณาสองBigDecimalวัตถุเท่ากันหากพวกเขามีค่าและขนาด (เท่ากับ 2.0 ดังนั้นจึงไม่เท่ากับ 2.00 เมื่อเปรียบเทียบกับวิธีนี้)

ในคำอื่น ๆ : equals()การตรวจสอบถ้าBigDecimalวัตถุตรงเหมือนกันในทุกด้าน compareTo()"เท่านั้น" เปรียบเทียบค่าตัวเลข

สำหรับสาเหตุที่ equals()ทำงานในลักษณะนี้สิ่งนี้ได้รับการตอบในคำถาม SOนี้


24
นั่นเป็นส่วนที่ยุ่งยากมากBigDecimalหากคุณไม่ได้อ่าน JavaDoc อย่างระมัดระวัง :) - เรามีข้อผิดพลาดบางอย่างจากเรื่องนี้จนกระทั่งเราตระหนักถึงความแตกต่าง
โทมัส

3
API มาตรฐานหลายส่วนเกิดขึ้นเพื่อกระทำการ "ไม่ตั้งใจ" เมื่อสิ่งที่ใช้งานง่ายจะไม่ถูกต้อง BigDecimalเป็นสิ่งหนึ่งที่ ดังนั้นหนึ่งควรตรวจสอบ JavaDoc อย่างน้อยหนึ่งครั้งที่คุณค้นพบสิ่งที่แปลกเกิดขึ้น
Joachim Sauer

7
ตลก. หลังจากอ่านคำตอบของคุณฉันเพิ่งตรวจสอบเปรียบเทียบและระบุว่าสอดคล้องกับเท่ากับ "ขอแนะนำอย่างยิ่ง (แต่ไม่จำเป็น)"
SJuan76

4
ฉันถามว่าทำไม: stackoverflow.com/questions/14102083/ …
bacar

8
@StephenC ฉันคิดว่ามันไม่ถูกต้องที่ความไม่สอดคล้องนี้มีอยู่
Matt R

1

ฉันเห็นว่า BigDecimal มีวิธีพอง () วิธีเท่ากับ () วิธี จริง ๆ แล้ว inflate () ทำอะไร

โดยทั่วไปinflate()สายBigInteger.valueOf(intCompact)ถ้าจำเป็นเช่นจะสร้างมูลค่า unscaled ที่ถูกเก็บไว้เป็นจากBigInteger long intCompactหากคุณไม่ต้องการสิ่งนั้นBigIntegerและค่าที่ไม่ลดขนาดนั้นควรเข้าlong BigDecimalกับการพยายามประหยัดพื้นที่ให้นานที่สุด


ฉันไม่รู้ว่าคุณเขียนอะไร (โดยเฉพาะประโยคสุดท้าย)
Buhake Sindi

@The ยอด Gentlement ประโยคสุดท้ายก็ควรจะบอกว่าภายในBigDecimalช่วยให้ค่า unscaled ของมันในเช่นเดียวกับlong BigIntegerหากBigIntegerไม่ต้องการภายในจะไม่ถูกสร้างขึ้น แต่ถ้าจำเป็น (เช่นเมื่อequalsพบการขยายตัวและพองตัวที่ไม่BigDecimal) พอง () `` ถูกใช้เพื่อสร้างมันขึ้นมา - เพื่อสรุป: inflate()จัดการกับการแปลงภายในถ้าจำเป็นและเนื่องจากมัน มีความเป็นส่วนตัวไม่ควรมีความสำคัญสำหรับผู้ใช้ในชั้นเรียน
Thomas

1

ฉันเชื่อว่าคำตอบที่ถูกต้องคือทำให้ตัวเลขทั้งสอง (BigDecimals) มีขนาดเท่ากันจากนั้นเราสามารถตัดสินใจเกี่ยวกับความเท่าเทียมกันของพวกเขา ตัวอย่างเช่นตัวเลขสองตัวนี้เท่ากันหรือไม่

1.00001 and 1.00002

มันขึ้นอยู่กับขนาด บนสเกล 5 (5 จุดทศนิยม) ไม่ใช่ว่าไม่เหมือนกัน แต่ในทศนิยมขนาดเล็ก (ขนาด 4 และต่ำกว่า) จะถือว่าเท่ากัน ดังนั้นฉันขอแนะนำให้ทำให้สเกลของตัวเลขสองตัวเท่ากันแล้วทำการเปรียบเทียบ


-10

คุณยังสามารถเปรียบเทียบกับค่าสองเท่า

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

5
โปรดหลีกเลี่ยงการแก้ปัญหานี้ให้มากที่สุด แม้แต่คู่ควรเปรียบเทียบกับ "epsilon" ไม่มีความรู้สึกที่จะมี BigDecimal และเปรียบเทียบเป็นคู่ ... มีความน่าจะเป็นสูงมากที่คุณจะยิงขาของคุณเอง
Vadim Kirilchuk

ค่า Douuble จะต้องเปรียบเทียบโดยใช้ epsillons
Bishwajit Purkaystha
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.