Szkolenia programowania we Wrocławiu
Kurs Java Podstawy - rozszerzony

Konwersja i Rzutowanie typów

Konwersja typów matematycznych

Zdarza się tak, że jeśli w jednej ze zmiennych przechowujemy jakieś dane typu A, to w pewnym momencie potrzebujemy tych samych danych, ale już w typie B. Najprostszy przykład, to taki, w którym mamy liczbę zadeklarowaną jako int, a następnie chcemy ją podzielić także przez typ int. Jak wiemy z wcześniejszych lekcji kursu będziemy mieli wtedy do czynienia z dzieleniem całkowitym i otrzymamy fałszywe wyniki. Oczywiście są pewne zasady, które można przedstawić w 4 prostych punktach:

  • Jeśli jeden z operandów jest typu double, to drugi także zostanie zamieniony na double
  • Lub, jeśli któryś z operandów jest typu float to drugi także zostanie zamieniony na float
  • Lub, jeśli któryś z operandów jest typu long, drugi także zostanie zamieniony na long
  • Gdy żadne z wyższych nie występuje oba typy zostaną zamienione na int

W skrócie możemy sobie wyobrazić, że przy działaniach matematycznych wszystkie zmienne są automatycznie konwertowane przez wirtualną maszynę Javy na najwyższy dostępny typ.

public class Konwersje{
  public static void main(String[] args){
	  int a = 5;
	  double b = 13.5;
	  double c = b/a;
	  System.out.println(c);
  }
}

Widzimy to działanie w powyższym przykładzie. Najpierw deklarujemy dwie zmienne a i b, odpowiednio typów int, oraz double. Następnie do zmiennej c przypisujemy wynik działania b/a. Czego się spodziewać w takiej sytuacji?

Przed podzieleniem typ zmiennej 'a' jest konwertowany na double dzięki czemu otrzymamy wynik zmiennoprzecinkowy, a nie całkowitoliczbowy. Należy uważać, aby nie popełnić błędu i nie próbować wymusić konwersji "w dół", czyli na przykład z typu double na int. Spowoduje to, że programu nie uda się nam skompilować.

public class Konwersje{
  public static void main(String[] args){
	  int a = 5;
	  double b = 13.5;
	  int c = b/a;               //TAK NIE MOŻNA ZROBIĆ!
	  System.out.println(c);
  }
}

W powyższym przykładzie próbujemy przypisać do zmiennej c typu int wynik ilorazu b/a, którym jest liczba zmiennoprzecinkowa 2.7. W takim wypadku kompilator zaprotestuje.

No dobrze, ale co zrobić, gdy faktycznie potrzebujemy zamienić typ double na int?

Rzutowanie (jawna konwersja)

Rzutowanie jest w przeciwieństwie do konwersji jawne i mamy na nie wpływ. Możemy wymusić konwersję z jednego typu na inny umieszczając uprzednio w okrągłych nawiasach typ docelowy.

	  int a = 5;
	  double b = 13.5;
	  int c = (int)b/a;

W takim wypadku błędu już nie będzie. Jednak musimy zdawać sobie sprawę, że takie postępowanie niesie ze sobą utratę części danych, w tym wypadku ucięcie części ułamkowej. W powyższym przykładzie najpierw następuje dzielenie, a następnie ucięcie(nie zaokrąglenie) wyniku. Aby otrzymać przybliżoną wartość wyniku należałoby użyć metody Math.round().

Konwersję możemy więc przedstawić jako niejawne rzutowanie:

	  int a = 5;
	  double b = 13.5;
	  double c = b/(double)a;

Na szczęście nie musimy tego zapisywać. Java zrobi to za nas automatycznie.

Zadania do samodzielnego wykonania:

1.6 Wykorzystaj konwersję i rzutowanie wypróbuj zamiany różnych typów prostych między sobą. Szczególną uwagę zwróć na rzutowanie char na int. Jak myślisz, co w ten sposób otrzymujesz?

Rozwiązanie

<- Poprzednia LekcjaNastępna Lekcja ->

Komentarze

Komentarze zamknięte. Zapraszamy do grupy na Facebooku
Marcin

Mały przykład konwersji typów:

kod:

public class ASCII{
public static void main(String[] args){
char znak;
for(int i = 0; i < 256;){
++i;
znak = (char)i;
System.out.print(i+" to "+znak+" ");
}
}
}

Witek

Inny przykład konwersji :


public class Demonstracja_Rzutowania {

/**
* Napisz program przedstawiający niektóre typy rzutowania i konwersji
* Wyniki przedstaw na konsoli
*
*/
public static void main(String[] args) {

double x = 15.0, y = 5.0;
byte b;
int i;
char ch,ch1;



// rzutowanie z double do int

i = (int) (x/y);
System.out.println("Wynik x/y oraz rzutowania do int to: " + i);

// rzutowanie z int do byte

i = 129;
b = (byte) i; //zakres typu byte : -128 do 127
System.out.println("Wynik rzutowania int do byte to: " + b);

// rzutowanie z byte do char

b = 67;
ch = (char) b;
System.out.println("Wynik rzutowania z byte do char to: " + ch);
System.out.println();

b = 10; // byte
i = b * b; // daje nam typ int
System.out.println("Wynik rzutowania jest typu int: " + i);

b = 9;
b = (byte)(b * b); // rzutujemy spowrotem do typu byte
System.out.println("Wynik rzutowania jest teraz typu byte: " + b);

ch = 'A';
ch1 = 'h';
ch = (char)(ch + ch1);
System.out.println("Wynik rzutowania typu char z powrotem do typu char to: " + ch);


}

}

NBT

"Rzutowanie (jawna konwersja)
Rzutowanie jest w przeciwieństwie do konwersji jawne i mamy na nie wpływ."
Czyż nie powinno być:
"Rzutowanie jest przeciwieństwem konwersji niejawnej, to znaczy, że mamy na nie wpływ"?

alfa

Dziwne to, taki prosty program :
public class KonwersjeAndRzutowanieTypów {
public static void main(String[] args) {
int a = 3;
double b = 10;
double c = b / a;
System.out.println(c);

}

}
W wyniku dostaje: 3.3333333333333335, skąd ta piątka na końcu, powinny być same trójki :/

Luigi

int c = (int)b/a;
"W powyższym przykładzie najpierw następuje dzielenie, a następnie ucięcie(nie zaokrąglenie) wyniku."
Nie do końca - operator rzutowania ma wyższy priorytet, więc najpierw następuje zrzutowanie zmiennej b do typu int, a następnie dokonane jest dzielenie liczb całkowitych :)

Jakub

Chcemy zrzutować (a+a*a),(gdzie a jest typu double) na int
double a;
int c=(int)(a+a*a);// czy może ma być
int c=(int)a+(int)a*(int)a;

SAK

Może być i tak i tak, ale wyjdą różne wyniki (przy znaczeniach a double)

ssss

Bardzo przystępnie wytłmaczone ;-)

mario

import java.util.Scanner;
public class tablice2 {

/**
* @param args
*/
public static void main(String[] args) {
System.out.println("Podaj liczbe");
Scanner odczyt = new Scanner(System.in);
int n = odczyt.nextInt();

int[] tablica = new int[n];

for(int i = n;i>0;i--){
tablica[i]=i+1;
}

while(n>0){
System.out.println(tablica[n]);
n++;
}

}

}
a tak czemu nie dziala?

Marcin Kunert

Na pierwszy rzut oka masz błąd w pętli. Zamiast i- powinno być raczej i--.

lolo

Mario na samej górze i tak samo pod polem do wpisywania komentarzy dostępny jest link do forum JavyStart. Taka mała uwaga tam lepiej jest zadawać pytania razem z kodem gdyż system komentarzy przekształca niektóre rzeczy podczas wysyłania np. cudzysłowie. Co trochę utrudnia pomoc.
Dobrze a teraz odnośnie kodu.
1.Jak to Marcin napisał już w linijce for(int i = n;i>0;i–){ powinien być podwójny minus(możliwe, że masz w kodzie ten podwójny minus i tylko system zamienił podczas wysyłania o czym wspomniałem wyżej)
2. Wstaw po linijce int[] tablica = new int[n];
n=n-1; i powinien program już zacząć działać bez zwracania błędów.
3. I mała rada zmień w linii for(int i = n;i>0;i–){ warunek i>0 na i>=0 oraz w linii while(n>0){ warunek n>0 na n>=0 bo wydaje mi się, że o to Ci chodziło.

Chłopek


//Chyba nie rozumiesz indeksowania tablic jeszcze ;)
for(int i = n;i>0;i- -){
tablica[i-1]=i+1;
}

while(n>0){
// Też błąd był, bo miałeś n++ co zawsze jest > 0, a po drugie indeksowanie tavblic zaczyna się od ZERA, więc np. w tablicy ośmioelementowej nie będzie indeksu nr 8. Ostatni to 7, a pierwszy to nr 0 ;)
System.out.println(tablica[- -n]);
}
Artur

Tyle glow i naprawde nikt nie zauwazyl jeszcze bledu. W pierwszym przykladzie dzielisz a/b i w drugim robisz to samo a/b zamiast b/a, drobny blad ale dla takich laikow jak ja to juz jest klopot z interpretacja.

Artur

Odwrotnie b/a zamiast a/b.

Sławek Ludwiczak

poprawione, dzięki :)