Odpowiedzi:
Dwa operandy (1 i 3) są liczbami całkowitymi, dlatego używana jest arytmetyka liczb całkowitych (tutaj dzielenie). Zadeklarowanie zmiennej wynikowej jako podwójnej powoduje po prostu niejawną konwersję po podzieleniu .
Dzielenie przez liczbę całkowitą zwraca oczywiście prawdziwy wynik dzielenia zaokrąglony do zera. Wynik funkcji 0.333...
jest zatem zaokrąglany w dół do 0. (Zwróć uwagę, że procesor w rzeczywistości nie wykonuje żadnego zaokrąglania, ale nadal możesz o tym myśleć w ten sposób).
Zwróć również uwagę, że jeśli oba operandy (liczby) są podane jako zmiennoprzecinkowe; 3.0 i 1.0, a nawet tylko pierwsza , a następnie używana jest arytmetyka zmiennoprzecinkowa, co daje 0.333...
.
DOWN
jest do zera. Zaokrąglanie w FLOOR
kierunku ujemnej nieskończoności.
1/3
używa dzielenia liczb całkowitych, ponieważ obie strony są liczbami całkowitymi.
Potrzebujesz co najmniej jednego z nich, aby być float
lub double
.
Jeśli wpisujesz wartości w kodzie źródłowym, tak jak twoje pytanie, możesz to zrobić 1.0/3
; to 1.0
jest podwójne.
Jeśli uzyskasz wartości z innego miejsca, możesz użyć ich (double)
do przekształcenia int
w double
.
int x = ...;
int y = ...;
double value = ((double) x) / y;
powinieneś użyć
double g=1.0/3;
lub
double g=1/3.0;
Dzielenie liczb całkowitych zwraca liczbę całkowitą.
Ponieważ robisz dzielenie liczb całkowitych.
Jak mówi @Noldorin, jeśli oba operatory są liczbami całkowitymi, używany jest dzielenie liczb całkowitych.
Wynik 0,33333333 nie może być reprezentowany jako liczba całkowita, dlatego do wyniku jest przypisywana tylko część całkowita (0).
Jeśli którykolwiek z operatorów to double
/ float
, to zostanie przeprowadzona arytmetyka zmiennoprzecinkowa. Ale będziesz miał ten sam problem, jeśli to zrobisz:
int n = 1.0 / 3.0;
Ponieważ traktuje 1 i 3 jako liczby całkowite, dlatego zaokrągla wynik w dół do 0, aby był liczbą całkowitą.
Aby uzyskać wynik, którego szukasz, wyraźnie powiedz javie, że liczby są podwojone, w następujący sposób:
double g = 1.0/3.0;
Konwersja w JAVA jest dość prosta, ale wymaga pewnego zrozumienia. Jak wyjaśniono w JLS dla operacji na liczbach całkowitych :
Jeśli operator liczby całkowitej inny niż operator przesunięcia ma co najmniej jeden operand typu long, to operacja jest wykonywana z 64-bitową precyzją, a wynik operatora numerycznego jest typu long. Jeśli drugi operand nie jest długi, jest on najpierw rozszerzany (pkt 5.1.5), aby wpisać long przez promocję liczbową (pkt 5.6).
A przykład to zawsze najlepszy sposób na przetłumaczenie JLS;)
int + long -> long
int(1) + long(2) + int(3) -> long(1+2) + long(3)
W przeciwnym razie operacja jest wykonywana z 32-bitową precyzją, a wynik operatora numerycznego jest typu int. Jeśli którykolwiek z operandów nie jest int, jest najpierw rozszerzany do typu int przez promocję liczbową.
short + int -> int + int -> int
Mały przykład użycia Eclipse, aby pokazać, że nawet dodanie dwóch short
znaków nie będzie takie łatwe:
short s = 1;
s = s + s; <- Compiling error
//possible loss of precision
// required: short
// found: int
Będzie to wymagało odlewania z możliwą utratą precyzji.
To samo dotyczy operatorów zmiennoprzecinkowych
Jeśli co najmniej jeden z operandów do operatora numerycznego jest typu double, to operacja jest wykonywana przy użyciu 64-bitowej arytmetyki zmiennoprzecinkowej, a wynikiem operatora numerycznego jest wartość typu double. Jeśli drugi operand nie jest podwójnym operatorem, jest najpierw rozszerzany (§5.1.5), aby wpisać double przez promocję liczbową (§5.6).
Tak więc promocja odbywa się na float w double.
A połączenie wartości całkowitej i zmiennoprzecinkowej daje wartości zmiennoprzecinkowe, jak powiedziano
Jeśli co najmniej jeden z operandów operatora binarnego jest typu zmiennoprzecinkowego, to operacja jest operacją zmiennoprzecinkową, nawet jeśli druga jest całka.
Dzieje się tak w przypadku operatorów binarnych, ale nie w przypadku „Operatorów przypisania”, takich jak +=
Aby to udowodnić, wystarczy prosty przykład roboczy
int i = 1;
i += 1.5f;
Powodem jest to, że wykonano tutaj niejawne rzutowanie, będzie to wykonane podobnie
i = (int) i + 1.5f
i = (int) 2.5f
i = 2
Najłatwiejszym rozwiązaniem jest po prostu to zrobić
double g = ((double) 1 / 3);
To, co robi, ponieważ nie wprowadziłeś 1.0 / 3.0, pozwala ręcznie przekonwertować go na typ danych double, ponieważ Java założyła, że jest to dzielenie całkowite, i zrobiłoby to, nawet jeśli oznaczałoby to zawężenie konwersji. Nazywa się to operatorem rzutowania.
Ja to zrobiłem.
double g = 1.0/3.0;
System.out.printf("%gf", g);
Użyj .0 podczas wykonywania podwójnych obliczeń, inaczej Java założy, że używasz liczb całkowitych. Jeśli Obliczenie wykorzystuje dowolną ilość podwójnych wartości, wynik będzie podwójną wartością. Jeśli wszystkie są liczbami całkowitymi, wynik będzie liczbą całkowitą.
(1/3) oznacza dzielenie całkowite, dlatego z tego dzielenia nie można uzyskać wartości dziesiętnej. Aby rozwiązać ten problem, użyj:
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);
}
Ponieważ zarówno 1, jak i 3 są liczbami całkowitymi, wynik nie jest zaokrąglony, ale jest obcięty. Więc ignorujesz ułamki i bierzesz tylko całość.
Aby tego uniknąć, miej przynajmniej jedną ze swoich liczb 1 lub 3 w postaci dziesiętnej 1.0 i / lub 3.0.
Wypróbuj to:
public static void main(String[] args) {
double a = 1.0;
double b = 3.0;
double g = a / b;
System.out.printf(""+ g);
}
Wykonaj „double g = 1,0 / 3,0;” zamiast.
Wielu innym nie udało się wskazać prawdziwego problemu:
Operacja tylko na liczbach całkowitych rzutuje wynik operacji na liczbę całkowitą.
To z konieczności oznacza, że wyniki zmiennoprzecinkowe, które mogą być wyświetlane jako liczby całkowite, zostaną obcięte (odcięcie części dziesiętnej).
Co to jest rzutowanie (rzutowanie / konwersja typów), o co pytasz?
Zależy to od implementacji języka, ale Wikipedia ma dość wszechstronny pogląd i mówi również o przymusie , który jest kluczową informacją w odpowiedzi na twoje pytanie.
1/2
W języku docelowym (java). Po prostu wywołujesz dzielenie liczb całkowitych, co da wynik w postaci liczby całkowitej. Rzutowanie typów jest spowodowane tylko konwersją w górę z int
na a double
podczas przypisywania.
0.5
. Po prostu w Javie 1/2
jest to dzielenie liczb całkowitych, które daje zerową liczbę całkowitą. Możesz przypisać zero do podwójnego, nadal będzie to zero, chociaż 0.0
podwójne.
int i = .99999999
ustawia int na 0. Dokładniej, pobiera część całkowitą, a resztę odrzuca.