Câu trả lời:
Hai toán hạng (1 và 3) là số nguyên, do đó số học nguyên (phép chia ở đây) được sử dụng. Khai báo biến kết quả là double chỉ gây ra một chuyển đổi ngầm định xảy ra sau khi chia .
Tất nhiên, phép chia số nguyên trả về kết quả thực sự của phép chia làm tròn về 0. Do đó, kết quả của 0.333...
được làm tròn xuống 0 ở đây. (Lưu ý rằng bộ xử lý không thực sự làm tròn bất kỳ, nhưng bạn vẫn có thể nghĩ về nó theo cách đó.)
Ngoài ra, lưu ý rằng nếu cả hai toán hạng (số) được cho dưới dạng số thực; 3.0 và 1.0, hoặc thậm chí chỉ là số học dấu phẩy động đầu tiên được sử dụng, mang lại cho bạn 0.333...
.
DOWN
là về 0. Làm tròn FLOOR
là về phía âm vô cùng.
1/3
sử dụng phép chia số nguyên vì cả hai bên đều là số nguyên.
Bạn cần ít nhất một trong số chúng để trở thành float
hoặc double
.
Nếu bạn đang nhập các giá trị trong mã nguồn như câu hỏi của mình, bạn có thể làm 1.0/3
; những 1.0
là một đôi.
Nếu bạn nhận được các giá trị từ nơi khác, bạn có thể sử dụng (double)
để biến int
thành a double
.
int x = ...;
int y = ...;
double value = ((double) x) / y;
bạn nên sử dụng
double g=1.0/3;
hoặc là
double g=1/3.0;
Phép chia số nguyên trả về số nguyên.
Bởi vì bạn đang thực hiện phép chia số nguyên.
Như @Noldorin đã nói, nếu cả hai toán tử đều là số nguyên thì phép chia số nguyên sẽ được sử dụng.
Kết quả 0.33333333 không thể được biểu diễn dưới dạng số nguyên, do đó chỉ phần nguyên (0) được gán cho kết quả.
Nếu bất kỳ toán tử nào là a double
/ float
, thì số học dấu phẩy động sẽ diễn ra. Nhưng bạn sẽ gặp vấn đề tương tự nếu bạn làm điều đó:
int n = 1.0 / 3.0;
Bởi vì nó coi 1 và 3 là số nguyên, do đó làm tròn kết quả xuống 0, để nó là một số nguyên.
Để có được kết quả bạn đang tìm kiếm, hãy nói rõ ràng với java rằng các con số sẽ tăng gấp đôi như vậy:
double g = 1.0/3.0;
Việc chuyển đổi trong JAVA khá đơn giản nhưng cần hiểu rõ. Như giải thích trong JLS cho các phép toán số nguyên :
Nếu một toán tử số nguyên không phải là toán tử shift có ít nhất một toán hạng kiểu dài, thì phép toán được thực hiện bằng cách sử dụng độ chính xác 64 bit và kết quả của toán tử số là kiểu dài. Nếu toán hạng khác không dài, thì đầu tiên nó được mở rộng (§5.1.5) để nhập dài bằng cách thăng hạng số (§5.6).
Và một ví dụ luôn là cách tốt nhất để dịch JLS;)
int + long -> long
int(1) + long(2) + int(3) -> long(1+2) + long(3)
Nếu không, hoạt động được thực hiện bằng cách sử dụng độ chính xác 32-bit và kết quả của toán tử số là kiểu int. Nếu một trong hai toán hạng không phải là int, thì đầu tiên nó sẽ được mở rộng để nhập int bằng cách thăng hạng số.
short + int -> int + int -> int
Một ví dụ nhỏ sử dụng Eclipse để chỉ ra rằng ngay cả việc thêm hai chữ short
s cũng không dễ dàng như vậy:
short s = 1;
s = s + s; <- Compiling error
//possible loss of precision
// required: short
// found: int
Điều này sẽ yêu cầu một quá trình đúc có thể mất độ chính xác.
Điều này cũng đúng đối với các toán tử dấu phẩy động
Nếu ít nhất một trong các toán hạng của toán tử số thuộc loại double, thì phép toán được thực hiện bằng cách sử dụng số học dấu phẩy động 64 bit và kết quả của toán tử số là giá trị của loại double. Nếu toán hạng khác không phải là một kép, thì trước tiên nó được mở rộng (§5.1.5) để nhập kép bằng cách thăng hạng số (§5.6).
Vì vậy, khuyến mãi được thực hiện trên phao thành đôi.
Và sự kết hợp của cả số nguyên và giá trị động dẫn đến các giá trị động như đã nói
Nếu ít nhất một trong các toán hạng của toán tử nhị phân thuộc kiểu dấu phẩy động, thì phép toán là phép toán dấu phẩy động, ngay cả khi phép toán kia là tích phân.
Điều này đúng với các toán tử nhị phân nhưng không đúng với "Toán tử gán" như +=
Một ví dụ làm việc đơn giản là đủ để chứng minh điều này
int i = 1;
i += 1.5f;
Lý do là có một phép ép kiểu ngầm được thực hiện ở đây, điều này sẽ được thực thi như
i = (int) i + 1.5f
i = (int) 2.5f
i = 2
1 và 3 là các hằng số nguyên và do đó Java thực hiện phép chia số nguyên mà kết quả là 0. Nếu bạn muốn viết các hằng số kép, bạn phải viết 1.0
và 3.0
.
Giải pháp đơn giản nhất là chỉ làm điều này
double g = ((double) 1 / 3);
Điều này làm được, vì bạn không nhập 1.0 / 3.0, cho phép bạn chuyển đổi thủ công sang kiểu dữ liệu kép vì Java cho rằng đó là phép chia Số nguyên và nó sẽ làm điều đó ngay cả khi nó có nghĩa là thu hẹp chuyển đổi. Đây là cái được gọi là toán tử ép kiểu.
Tôi đã làm điều này.
double g = 1.0/3.0;
System.out.printf("%gf", g);
Sử dụng .0 trong khi thực hiện các phép tính kép, nếu không Java sẽ cho rằng bạn đang sử dụng Số nguyên. Nếu một Phép tính sử dụng bất kỳ số lượng giá trị kép nào, thì kết quả đầu ra sẽ là giá trị kép. Nếu tất cả đều là Số nguyên, thì đầu ra sẽ là Số nguyên.
(1/3) có nghĩa là phép chia Số nguyên, đó là lý do tại sao bạn không thể nhận giá trị thập phân từ phép chia này. Để giải quyết vấn đề này, hãy sử dụng:
public static void main(String[] args) {
double g = 1.0 / 3;
System.out.printf("%.2f", g);
}
public static void main(String[] args) {
double g = 1 / 3;
System.out.printf("%.2f", g);
}
Vì cả 1 và 3 đều là số nguyên nên kết quả không được làm tròn mà bị cắt bớt. Vì vậy, bạn bỏ qua phân số và chỉ lấy sỉ.
Để tránh điều này, hãy có ít nhất một trong các số 1 hoặc 3 của bạn ở dạng thập phân 1,0 và / hoặc 3,0.
Thử thứ này đi:
public static void main(String[] args) {
double a = 1.0;
double b = 3.0;
double g = a / b;
System.out.printf(""+ g);
}
Làm "double g = 1.0 / 3.0;" thay thế.
Nhiều người khác đã không chỉ ra được vấn đề thực sự:
Một phép toán chỉ trên số nguyên chuyển kết quả của phép toán thành một số nguyên.
Điều này nhất thiết có nghĩa là kết quả dấu phẩy động, có thể được hiển thị dưới dạng số nguyên, sẽ bị cắt bớt (bỏ phần thập phân).
Bạn yêu cầu truyền (đánh máy / chuyển đổi kiểu) là gì?
Nó khác nhau về việc triển khai ngôn ngữ, nhưng Wikipedia có một cái nhìn khá toàn diện và nó cũng nói về sự ép buộc , đây là một phần thông tin quan trọng để trả lời câu hỏi của bạn.
1/2
, không phải trong ngôn ngữ đích (java). Bạn chỉ cần gọi một phép chia số nguyên, điều này sẽ dẫn đến kết quả là số nguyên. Kiểu Truyền chỉ là do chuyển đổi lên từ int
thành a double
trong quá trình gán.
0.5
. Đơn giản, trong Java, 1/2
là một phép chia số nguyên, dẫn đến một số nguyên bằng không. Bạn có thể gán số 0 cho số kép, nó sẽ vẫn là số 0, mặc dù là số 0.0
kép.
int i = .99999999
đặt int thành 0. Cụ thể hơn, nó lấy phần nguyên và loại bỏ phần còn lại.