2010-03-04 41 views
60

Tôi có mã để tính chênh lệch tỷ lệ phần trăm giữa 2 số - (oldNum - newNum)/oldNum * 100; - trong đó cả hai số là double s. Tôi dự kiến ​​sẽ phải thêm một số loại kiểm tra/xử lý ngoại lệ trong trường hợp oldNum là 0. Tuy nhiên, khi tôi chạy thử nghiệm với các giá trị 0.0 cho cả oldNum và newNum, thực thi tiếp tục như thể không có gì xảy ra và không có lỗi nào bị ném. Chạy mã này với int s chắc chắn sẽ gây ra một ngoại lệ số học-by-zero. Tại sao Java bỏ qua nó khi nói đến double s?Tại sao Java không ném ngoại lệ khi chia cho 0.0?

+4

Câu hỏi hay - sự không thống nhất giữa số nguyên và hành vi kép làm tăng thêm sự nhầm lẫn và rắc rối. –

+2

bản sao có thể có của [Tại sao phân chia bằng không với số dấu chấm động (hoặc độ chính xác gấp đôi) không ném java.lang.ArithmeticException:/bằng 0 trong Java] (http://stackoverflow.com/questions/12954193/why-does- chia-by-zero-với-floating-point-hoặc-double-precision-numbers-not) – Raedwald

+2

@Raedwald - xem xét câu hỏi này đã được đăng 2 1/2 năm trước khi bạn liên kết, tôi sẽ nói câu hỏi đó là (có thể) trùng lặp cái này :) – froadie

Trả lời

42

Kết quả của phép chia cho không, nói về mặt toán học, không xác định, có thể được thể hiện với một phao/đôi (như NaN - không phải là một số), nó là không, tuy nhiên, sai trong bất kỳ ý nghĩa cơ bản.

Là số nguyên phải giữ giá trị bằng số cụ thể, lỗi phải được chia thành số không khi xử lý chúng.

+6

Chính xác. Điều này được định nghĩa trong Java Language Spec ở đây: http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.2.3 –

+1

Tôi đã thử xuất kết quả, và nó là một giá trị NaN. Điều đó có nghĩa là int không thể giữ NaN? – froadie

+1

nhưng đây là trường hợp của '0.0/0.0' là NaN. –

4

Cách một đôi được lưu trữ hoàn toàn khác với int. Xem http://firstclassthoughts.co.uk/java/traps/java_double_traps.html để có giải thích chi tiết hơn về cách Java xử lý các phép tính kép. Bạn cũng nên đọc các số Floating Point, đặc biệt là khái niệm về Not a Number (NaN).

Nếu bạn quan tâm đến việc tìm hiểu thêm về đại diện điểm nổi, tôi khuyên bạn nên đọc this document (Định dạng Word, xin lỗi). Nó đào sâu vào biểu diễn nhị phân của các số, có thể hữu ích cho sự hiểu biết của bạn.

101

Java floatdouble loại, giống như khá nhiều bất kỳ ngôn ngữ nào khác ngoài kia (và khá nhiều bất kỳ đơn vị FP phần cứng), thực hiện các tiêu chuẩn IEEE 754 cho nổi toán điểm, mà ủy nhiệm phép chia cho không trở về một "vô cực" giá trị đặc biệt . Ném một ngoại lệ sẽ thực sự vi phạm tiêu chuẩn đó.

Số nguyên nguyên (được thực hiện dưới dạng Java và hầu hết các ngôn ngữ và phần cứng khác) và không có giá trị vô hạn hoặc NaN đặc biệt, do đó, ném ngoại lệ là một hành vi hữu ích ở đó.

+3

Câu trả lời đúng cho câu hỏi này nên là điều này. Tôi cần biết tại sao 'float' và' double' không gây ra ngoại lệ. Cảm ơn. –

+1

Đây phải là câu trả lời chính xác được đánh dấu.Câu trả lời hiện được đánh dấu là chính xác không trả lời được câu hỏi, cũng không làm rõ rằng Java đang theo chuẩn IEEE 754. – Necrototem

3

Mặc dù các nhà phát triển Java biết về loại nguyên thủy đôi và Double lớp, trong khi làm nổi điểm số học họ không chú ý đủ để Double.INFINITY, NaN, -0.0 và các quy tắc khác chi phối các tính toán số học liên quan đến họ.

Câu trả lời đơn giản cho câu hỏi này là nó sẽ không ném ArithmeticException và trả lại Double.INFINITY. Ngoài ra, hãy lưu ý rằng so sánh x == Double.NaN luôn luôn đánh giá là false, ngay cả khi x chính nó là NaN.

Để kiểm tra xem x có phải là NaN không, hãy sử dụng phương thức gọi Double.isNaN(x) để kiểm tra xem số đã cho có phải là NaN hay không. Địa chỉ này rất gần với NULL trong SQL.

Nó có thể hữu ích cho bạn.

1

Khi chia cho zero (0 hoặc 0,00)

  1. Nếu bạn chia đôi bởi 0, JVM sẽ hiển thị Infinity.

    public static void main(String [] args){ double a=10.00; System.out.println(a/0); }

    Console: Infinity

  2. Nếu bạn chia int bằng 0, sau đó JVM sẽ ném Arithmetic Exception.

    public static void main(String [] args){ int a=10; System.out.println(a/0); }

    Console: Exception in thread "main" java.lang.ArithmeticException:/by zero

  3. Nhưng nếu chúng ta chia int bằng 0,0, sau đó JVM sẽ hiển thị Infinity:

    public static void main(String [] args){ int a=10; System.out.println(a/0.0); }

    Console: Infinity

Điều này là do JVM sẽ tự động gõ int int để tăng gấp đôi, vì vậy chúng tôi nhận được vô cùng thay vì ArithmeticException.

Các vấn đề liên quan