Преобразование типов

Открыта

— А теперь самое интересное. Я расскажу тебе про преобразование типов. Хоть типы переменных всегда неизменны, есть место, где можно проводить преобразование типов. И место это – присваивание.

— Можно присваивать друг другу переменные разных типов. При этом значение, взятое из переменной одного типа, будет преобразовано в значение другого типа и присвоено второй переменной.

— В связи с этим, можно выделить два вида преобразования типов: расширение и сужение. Расширение похоже на перекладывание из маленькой корзинки в большую – операция проходит незаметно и безболезненно. Сужение типа – это перекладывание из большой корзинки в маленькую: места может не хватить, и что-то придётся выбросить.

-Вот типы, отсортированные по размеру «корзинки»:

Преобразование типов

— Тут есть пара замечаний:

1. char такая же корзинка, как и short, но свободно перекладывать из одной в другую нельзя: при перекладывании значения из short в char, всегда будут теряться значения меньше 0. При перекладывании из char в short будут теряться значения больше 32-х тысяч.

2. При преобразовании из целых чисел в дробные могут отбрасываться самые младшие части числа. Но т.к. смысл дробного числа в том, чтобы хранить приблизительное значение, то такое присваивание разрешается.

При сужении типа мы должны явно показать компилятору, что мы не ошиблись и отбрасывание части числа сделано намеренно. Для этого используется оператор приведения типа. Это имя типа в круглых скобочках.

— Вот как нужно присваивать переменные разных типов:

Код на Java Описание
byte a = 115;
int b = a;
Расширение типа. Все отлично.
int c = 10000;
byte d = (byte) c;
Сужение типа. Нужно явно отбросить лишние байты.
int c = 10;
byte d = (byte) c;
Сужение типа. Нужно явно отбросить лишние байты, даже если они равны 0.
float f = 10000;
long l = (long) (f * f);
float f2 = l;
long l2 = (long) f2;
При присваивании к float, происходит расширение типа. При присваивании значения float к long, происходит сужение – необходимо приведение типа.
double d = 1;
float f = (float) d;
long l = (long) f;
int i = (int) l;
short s = (short) i;
byte b = (byte) s;
Сужение во всех операция присваивания, кроме первой строки, требует указания явного преобразования типа.
3
Задача
Java Syntax,  10 уровень,  3 лекция
Недоступна
Набираем код Ӏ Java Syntax: 10 уровень, 3 лекция
Java Syntax: 10 уровень, 3 лекция. Иногда думать не надо, строчить надо! Как ни парадоксально звучит, порой пальцы «запоминают» лучше, чем сознание. Вот почему во время обучения в секретном центре JavaRush вы иногда встречаете задания на набор кода. Набирая код, вы привыкаете к синтаксису и зарабатываете немного материи. А ещё — боретесь с ленью.

Оператор приведения типа нужно указывать перед числом/переменной каждый раз, когда происходит отбрасывание части числа или сужение типа. Он действует только на число/переменную, которое идет непосредственно за ним.

Код на Java Описание
float f = 10000;
long l = (long) f * f;
К типу long приводится только одна переменная из двух: умножение long и float дает float. Данный пример кода не будет скомпилирован.
float f = 10000;
long l = (long) (f * f);
Тут все выражение приводится к типу long. Этот пример кода будет скомпилирован.

— Ясно.

Комментарии (138)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий вы должны авторизоваться
Михаил19 уровень, Москва
2 августа, 16:06
2. При преобразовании из целых чисел в дробные могут отбрасываться самые младшие части числа. Но т.к. смысл дробного числа в том, чтобы хранить приблизительное значение, то такое присваивание разрешается.
Точно так? Если отбросить от целого числа младшие части, то получится ошибка на порядки. Похоже, что наоборот? Косноязычно написано, или я не так смысл понял?
Иван16 уровень, Рязань
6 августа, 09:20
Такой же вопрос, почему дробное число это приблизительное значение? наоборот же точное
OldTiredMan14 уровень
20 августа, 14:11
дробные числа точные только пока они в виде дроби целых чисел, например 1/3. а когда эта 1/3 представлена в виде 0.33333 - то это приблизительное значение, и его "точность" определяется количеством знаков после запятой. у флоата она поменьше, у дабла побольше.
Станислав10 уровень, Санкт-Петербург
3 сентября, 06:50
если я правильно понимаю, то число 123456 и число 0.12345 хранятся одинаково. То есть 12345 будет хранится как 12345, а его дробный аналог будет такой же только 12345(5) где последняя (5) - количество знаков после запятой. То есть оно будет требовать в любом случае на одну единицу памяти больше. Поэтому крайне большие целые числа, которые еле влезают в память для целых чисел, уже могут не поместиться в память для дробных.
Алиса23 уровень, Санкт-Петербург
14 сентября, 17:04
посмотрите в сторону "проблемы точности десятичных дробей в ЯП". есть прекрасные примеры того как x(= 0.2) * 0.3 != 0.6. связано это с тем, что x на самом деле равен условным 0.2000000001. Происходит так потому, что данные в большинстве ЯП хранятся не в десятичной системе.
Алиса23 уровень, Санкт-Петербург
14 сентября, 17:08
А конкретно в java хранится только 6-7 знаков после запятой, что и делает ее условно неточной. На тему java - личное мнение, основанное на предыдущей лекции)
Metamorphogenesis10 уровень
вчера, 12:51
ошибку на порядок вы как раз компенсируете степенью десятки, которая займет в значении место отброшенных младших разрядов. грубо говоря вместо 123456789 вы получите 1.234567*Е+08 (что равнозначно 123456700). Числа отличаются не на порядок, а всего лишь на 89, которые были отброшены от целого числа, чтобы освободить место для степени, а это 0,0007209%. Я написал чисто условно, чтобы наглядно показать, зачем отбрасывать младшие разряды и почему это уменьшает точность, но в принципе тут видно, что потери не так велики, чтобы о них переживать.
Ivan18 уровень, Череповец
5 июня, 14:42
Вот чего-то не хватало и я посмотрел три ролика на youtube и вроде как всё упаковалось в голове: Из двоичной в десятичную Из десятичной в двоичную Перевод чисел между системами счисления
Mao4ka13 уровень, Москва
16 июня, 18:25
последнее видео очень интересное
Александр К.11 уровень
29 августа, 11:42
Спасибо за ссылки. Первые два интересные видео. Последнее - крайне занимательное 👍
Дмитрий Ильин20 уровень, Cheboksary
27 мая, 13:45
При присваивании значения float к long, происходит сужение – необходимо приведение типа. Смущает? смотри внимательно предыдущую лекцию тут Выводы: 1.У long диапазон значений меньше чем у float, поэтому происходит сужение, хотя у long-8 байт , float - 4 байта. 2. При переводе float к long отбрасывается дробная часть.
Людмила15 уровень, Санкт-Петербург
8 июля, 17:17
Смутило, да) Спасибо
Люда13 уровень, Москва
20 мая, 16:28
мне одной кажется что эти статьи нужны были на уровне 3 или 4?
Михаил15 уровень
28 апреля, 15:14
Объясните пожалуйста это: float f = 10000; long l = (long) (f * f); Просто я бы по аналогии сделал так: float f = 10000; long l = (long) f; Почему f*f ??
satird26 уровень, Минск
30 апреля, 10:25
Если нужно перемножить два float и результат привести в long нужно КАЖДЫЙ привести к long.
float f = 10000;
long l = (long) f * (long) f;
Zelimkhan19 уровень, Грозный
11 апреля, 10:34
Подскажите парни, я вообще не шарю этих системах счисления или как их. В будущем они мне понадобятся? Стоит ли изучить? Если стоит, можете тыкнуть нормальные ресурсами
Иван20 уровень, Москва
11 апреля, 18:47
пригодятся. изучи. но у меня ссылок на доп. информацию нет. попробуй поискать в разделе PRO
Игорь Кучер38 уровень, Киев
25 мая, 16:50
в тестах будут вопросы 100%
Halfar22 уровень, Пермь
2 апреля, 10:40
- Если Вы "кладёте" в больший контейнер содержимое меньшего контейнера», преобразование происходит автоматически, и ошибок возникать не должно. - Если есть необходимость положить «значение из большего контейнера в меньший», нужно быть осторожным, и пользоваться явным приведением типов. -При приведении float или double к целочисленным типам, дробная часть не округляется, а просто отбрасывается. - Тип boolean не приводится ни к одному из типов. - Тип char приводится к числовым типам, как код символа в системе UNICODE. - Если число больше своего контейнера, результат будет непредсказуемым.
Сергей11 уровень, Ekaterinburg
10 марта, 04:57
Я понимаю, что это продолжение лекции. Всем спасибо!
Александр C31 уровень, Ростов-на-Дону
26 февраля, 07:49
Почему "При присваивании значения float к long, происходит сужение – необходимо приведение типа." Ведь long 8 байт а float 4?
Sergey Tsvelovsky33 уровень, Москва
29 февраля, 10:32
long не хранит дробную часть поэтому ему придется отбрасывать лишние байты.
Sergey Tsvelovsky33 уровень, Москва
29 февраля, 10:36
плюс во float больше диапазон значений, чем в long. от -10^127 до + 10^127 (у лонг от -9^18 до +9^18), это достигается за счет выделения мантиссы и экспоненты в два разных числа (в прошлой лекции об этом написано)
Владислав19 уровень, Санкт-Петербург
25 мая, 07:14
да, но надо учитывать, что у float вроде около 7 значащих цифр)
Евгений41 уровень, Нижний Новгород
26 января, 17:25
А при приведении типов, усечение вот так вот происходит (вдруг кто-то не представляет, как именно): число 258, например в двоичном коде будет 100000010, и, например у нас код:
int a = 258;
byte b = (byte) a;
То тут для преобразования int в byte (4-байтная система в 1-байтную) будет отсечено всё, что идёт слева от крайних 8 правых ячеек. Вот у нас код 100000010, а отсечено будет вот это 100000010, и получится 00000010, что в двоичной системе значит 2.
Илья 14 уровень, Москва
2 февраля, 17:12
так-то да, но idea выдаст b как 0.
Евгений41 уровень, Нижний Новгород
2 февраля, 17:35
Виноват, моя ошибка, хотел написать 258. Число 256 будет 100000000. Соответственно, отбрасывается всё, что идёт раньше последних восьми ячеек и 00000000 уже соответствует 0. А вот 258 после преобразование к byte будет уже 2.
Андрей15 уровень, Москва
23 февраля, 11:18
Действительно так 00000000 00000000 00000001 00000010 int дес 258 00000010 byte дес 2
Андрей12 уровень, Самара
13 апреля, 18:40
Еще можно представить byte b как остаток от деления int на 256... где 256 - это количество значений, которое может принимать число типа byte.