2012-05-07 18 views
5

có điều gì đó khiến tôi khó hiểu và tôi không tìm thấy nhiều thông tin về các thông số kỹ thuật của máy ảo. Đó là một chút mơ hồ và đó sẽ là tốt đẹp nếu ai đó có thể giải thích cho tôi.Đúc một đôi sang kiểu số khác

Những vài dòng mã .....

double myTest = Double.MAX_VALUE; 

System.out.println("1. float: " + (float)myTest); 
System.out.println("2. int: " + (int)myTest); 
System.out.println("3. short: " + (short)myTest); 
System.out.println("4. byte: " + (byte)myTest); 

..... sản xuất sản lượng này:

  1. float: Infinity
  2. int: 2147483647
  3. ngắn: -1
  4. byte: -1

byte, shortint là 8, 16, 32 bit với phần bổ sung của hai. floatdouble là 32 và 64 bit IEEE 754 (see here). Từ sự hiểu biết của tôi, giá trị tối đa của một double ngụ ý rằng tất cả các bit của mantisse (52 bit) được chuyển sang 1. Vì vậy, nó không phải là (rất) đáng ngạc nhiên rằng một diễn viên để ngắn hoặc trả về byte -1 tức là tất cả các bit được chuyển sang 1. Có vẻ như các diễn viên giữ 'đuôi' của double để nó phù hợp với 8 bit byte hoặc 16 bit short.

Điều khiến tôi bất ngờ là dàn diễn viên đến int và ở mức độ thấp hơn, dàn diễn viên đến float. Làm thế nào để có thể nhận được "2. int: 2147483647" là 0x7FFFFFFF, giá trị tối đa trong khi ngắn và byte 3. và 4. là -1?

Truyền tới float cũng lạ. Nếu 32 bit ở 'đuôi' của myTest được giữ, thì không nên tạo ra một bit NaN?

Trả lời

4

JLS giải thích các quy tắc trong phần 5.1.3 Narrowing Primitive Conversion. Các quy tắc phụ thuộc vào loại mục tiêu.

float:

Chuyển đổi nguyên thủy thu hẹp từ đôi nổi được điều chỉnh bởi IEEE 754 quy tắc làm tròn (§4.2.4). Chuyển đổi này có thể mất độ chính xác, nhưng cũng mất phạm vi, dẫn đến một số không bằng 0 từ một nonzero đôi và một vô cực nổi từ một đôi hữu hạn. Một NaN kép được chuyển đổi thành một NaN dạng float và một vô cực kép được chuyển đổi thành vô cực cùng ký.

intlong:

một trong hai trường hợp sau đây phải đúng:

  • ...
  • Giá trị phải là quá lớn (giá trị dương có độ lớn hoặc vô cực) và kết quả của bước đầu tiên là giá trị thể hiện lớn nhất của loại int hoặc dài.

byte, charshort:

Nếu loại mục tiêu là byte, char hoặc short, việc chuyển đổi nó gồm hai bước. Đầu tiên, double được chuyển đổi thành long như được giải thích ở trên. Sau đó, long được chuyển đổi sang các loại thức như sau:

Chuyển đổi hẹp của một số nguyên ký hợp đồng với một loại tách rời T chỉ đơn giản là loại bỏ tất cả ngoại trừ các bit thứ tự n thấp nhất, trong đó n là số bit được sử dụng để đại diện cho loại T. Ngoài khả năng mất thông tin về độ lớn của giá trị số, điều này có thể khiến dấu của giá trị kết quả khác với dấu của giá trị đầu vào.

+0

Cảm ơn điều này rất thú vị. Vì vậy, khi double được cast thành một int ("với giá trị đại diện lớn nhất" trong ví dụ của tôi), nó được đúc thành một byte hoặc ngắn với một triết lý khác ("loại bỏ tất cả trừ bit thứ tự thấp nhất"). – Jerome

+0

@Jerome: Khá nhiều (ngoại trừ việc tôi nghĩ rằng loại trung gian là 'long', nhưng không ảnh hưởng đến kết quả). – NPE

+0

Cần lưu ý rằng mặc dù việc tạo 'double' thành' float' có thể gây ra một số giá trị khác biệt để trở thành không thể phân biệt được, đó là một vấn đề nhỏ so với thực tế rằng việc đưa 'float' sang' double' có thể gây ra những thứ nên được xem là không thể phân biệt được được sắp xếp * sai *. Ví dụ, cho 'float f = 16777217; double d = 16777216.0000001; ', lớn hơn - 'f' hoặc' d'? Làm thế nào về 'float ff = 1E38f * 10f; double dd = 1e300; '? Về 'ff' và' dd' là "không thể phân biệt" sẽ không tuyệt vời, nhưng nói 'ff> dd' là sai số hàng trăm đơn vị. – supercat