2012-02-01 14 views
16

Tôi có một phương thức trong java trả về một số kép và tôi muốn so sánh mọi số kép được trả về mỗi khi tôi gọi phương thức (nói 5 lần), để tôi có thể kết luận rằng số được trả về gần như giống nhau thời gian.Làm thế nào để so sánh chuỗi thứ hai đó là tất cả "gần bằng nhau" trong Java?

Tôi làm cách nào để thực hiện việc này?

+2

Bạn có thể nói thêm về bối cảnh? Bạn đang làm điều này từ một bài kiểm tra đơn vị? Trong trường hợp đó, một trong các assertEquals trong JUnit chỉ có một phương pháp để khẳng định rằng hai đôi là gần. –

+0

Cảm ơn mọi người đã trả lời. Vì vậy, có, tôi đang cố gắng để làm một bài kiểm tra đơn vị, và phương pháp của tôi trả về thời gian mà một số số nguyên được thêm vào một mảng. Tôi muốn thử nghiệm phương pháp này với số lượng khác nhau của các số nguyên và so sánh thời gian. Tôi đoán phương thức ulp() có thể hoạt động. – FranXh

Trả lời

6

Trước tiên, bạn phải quyết định ý nghĩa của "gần như giống nhau". Ví dụ: có một phương thức trong số java.lang.Math được gọi là ulp(), trong đó, được tính gấp đôi, trả về khoảng cách giữa giá trị đó gấp đôi và lần tiếp theo; tức là sự khác biệt nhỏ nhất có thể giữa số đó và bất kỳ khác nào. Bạn có thể chỉ cần so sánh sự khác biệt giữa hai đôi và kết quả của việc gọi phương thức đó.

Mặt khác, có thể bạn muốn hai số chỉ nằm trong phạm vi 1% của nhau. Trong trường hợp đó, hãy thực hiện cùng một tính toán, nhưng sử dụng số đầu tiên nhân với 0.01 thay vì ulp() là khoảng cách chấp nhận được lớn nhất.

+0

Cảm ơn mọi người đã trả lời. Vì vậy, có, tôi đang cố gắng để làm một bài kiểm tra đơn vị, và phương pháp của tôi trả về thời gian mà một số số nguyên được thêm vào một mảng. Tôi muốn thử nghiệm phương pháp này với số lượng khác nhau của các số nguyên và so sánh thời gian. Tôi đoán phương thức ulp() có thể hoạt động. – FranXh

6

Bình đẳng gần đúng được xác định theo sự khác biệt tuyệt đối: nếu chênh lệch tuyệt đối không vượt quá số lượng, có lẽ nhỏ, thì bạn có thể nói rằng giá trị bạn so sánh là "đủ gần".

double diff = Math.abs(actual - expected); 
if (diff < 1E-7) { 
    // Numbers are close enough 
} 

Bạn phải rất cẩn thận để không nhầm lẫn giữa "đủ gần" kết thúc "bằng", vì hai về cơ bản khác nhau: bình đẳng là bắc cầu (ví dụ: a == b và b == c cùng ngụ ý rằng a = = c), trong khi "đóng đủ" không phải là chuyển tiếp.

1

Điều gì có nghĩa là hai cặp đôi "tương đương nhau"? Nó có nghĩa là đôi bên trong một số khoan dung của nhau. Kích thước của sự khoan dung đó, và liệu sự khoan dung đó có được biểu thị như một con số tuyệt đối hay là một tỷ lệ phần trăm của hai đôi, phụ thuộc vào ứng dụng của bạn. Ví dụ: hai ảnh được hiển thị trên trình xem ảnh có cùng chiều rộng bằng inch nếu chúng chiếm cùng số pixel trên màn hình, do đó dung sai của bạn sẽ là số tuyệt đối được tính dựa trên kích thước pixel cho màn hình của bạn . Mặt khác, lợi nhuận của hai công ty tài chính có thể "xấp xỉ bằng nhau" nếu chúng nằm trong phạm vi 0,1% của nhau. Đây chỉ là những ví dụ giả định, nhưng vấn đề là nó phụ thuộc vào ứng dụng của bạn.

Bây giờ, để thực hiện một số. Giả sử ứng dụng của bạn yêu cầu tuyệt đối. Sau đó, bạn có thể sử dụng

private static final double TOLERANCE = 0.00001; 

public static boolean approxEqual(final double d1, final double d2) { 
    return Math.abs(d1 - d2) < TOLERANCE; 
} 

để so sánh hai đôi, và sử dụng

approxEqual(d1, d2) && approxEqual(d1, d3) && approxEqual(d1, d4) && approxEqual(d1, d5) 

để so sánh lăm đôi.

26
public static boolean almostEqual(double a, double b, double eps){ 
    return Math.abs(a-b)<eps; 
} 

Trường hợp eps là thước đo bình đẳng.

+0

Tôi lấy quyền tự do xóa bỏ một ')' –

+2

'Math.abs ((ab)/a) sffc

4

Điều đó tùy thuộc vào ý bạn. Nếu bạn muốn so sánh hai số trong một lỗi tuyệt đối, ví dụ: 1e-6 bạn có thể sử dụng epsilon. Nếu bạn muốn so sánh hai số double bất kể tỷ lệ. ví dụ. 1.1e-20 và 1.3e-20 không giống nhau nhưng 1.1e20 và 1.1e20 + 1e5 là bạn có thể so sánh giá trị thô.

public static void main(String... args) throws IOException { 
    test(1.1e-20, 1.3e-20); 
    test(1.1e20, 1.1e20 + 1e5); 
} 

private static void test(double a, double b) { 
    System.out.println(a + " and " + b + ", similar= " + similarUnscaled(a, b, 10)); 
} 

public static boolean similarUnscaled(double a, double b, long representationDifference) { 
    long a2 = Double.doubleToRawLongBits(a); 
    long b2 = Double.doubleToRawLongBits(b); 
    // avoid overflow in a2 - b2 
    return ((a2 >= 0) == (b2 >= 0)) && 
      Math.abs(a2 - b2) <= representationDifference; 
} 

in

1.1E-20 and 1.3E-20, similar= false 
1.1E20 and 1.100000000000001E20, similar= true 
+1

Cẩn thận với mô hình chung của việc so sánh sự khác biệt với 0 với điều này. Khoảng 0 nó trở nên đột nhiên rất nhạy cảm: 'tương tựUnscaled (0.69/3, 0.23, 10)! = SimilarUnscaled (0.69/3 - 0.23, 0, 10)' – georg