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

Открыта

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

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

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

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

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

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

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. Этот пример кода будет скомпилирован.

— Ясно.

Комментарии (143)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий вы должны авторизоваться
26 января, 02:19
Ребята, подскажите пожалуйста, как это понимать: "При преобразовании из целых чисел в дробные могут отбрасываться самые младшие части числа. " Какие младшие части числа у целого числа?
Flexo Bending Unit #3370318
4 февраля, 07:08
числа наименьших разрядов у числа 1234567 это, например, 7
Zav_O
19 уровень, Москва
17 марта, 08:03
10001==10*10^3
Александр
22 уровень, Тамбов
21 декабря 2020, 08:23
Возможно будет полезно! Правила продвижения типов из книги Шилдта. Сначала все значения типа byte, short и char продвигаются к типу int. Затем тип всего выражения продвигается к типу long, если один из его операндов относится к типу long. Если же один из операндов относится к типу float, то тип всего выражения продвигается к типу float. А если любой из операндов относится к типу double, то и результат вычисления всего выражения относится к типу double.
Тони
10 уровень, Москва
10 декабря 2020, 12:59
Я правильно понимаю, что float более "вместительнее" чем long ? вроде: float = 4, а long = 8.
Justinian Judge в Mega City OneMaster
3 января, 23:25
конечно. Вот пример Long: 1 (1L) вот пример float: 1.12355 (1.12355f) как видим, float вмещает больше информации чем Long и имеет большую точность, поэтому float шире. Но и по самим значениям float на многие порядки вместительнее long: максимальное значение для Long -> 2^63-1 максимальное значение для float -> (3.4)*10^38 а что что размер float меньше, это не важно, поскольку float по другому хранит данные. Ну например что больше, число, запись которого помещается в 8 символов или число, запись которого помещается в 5 символов? Первое число: 10 000 000 -> 10 млн, 8 символов. Второе число: 10^18 -> 10 в 18 степени или один квинтиллион, записывается 5 символами
Тони
10 уровень, Москва
21 января, 12:49
Спасибо
Антон
20 уровень, Москва
4 декабря 2020, 20:34
Zav_O
19 уровень, Москва
17 марта, 08:06
Всегда захожу в комментарии ради таких ссылок, спасибо тебе, добрый человек
🦔 Виктор веду Java Android канал в telegram @LetsCodeItExpert
6 ноября 2020, 16:21
Now we're talking! Однозначно в закладки. p.s. Тут чуть ниже замечательный комментарий от Судьи Дредда есть, который поясняет за сужения/расширения ; )
Антон Володин
26 уровень, Комсомольск-на-Амуре
5 ноября 2020, 05:44
int c = 10000;
byte d = (byte) c;
System.out.println(d);
Почему в итоге выдает 16?
Димитрий
24 уровень, Саратов
5 ноября 2020, 11:54
Тип byte ограничен диапазоном от -128 до 127 (всё включительно). Если, например, в byte поместить int c = 128, то получим -128. Проще говоря, если значение типа выходит за границы типа, в который мы пытаемся поместить (int>byte), то значения идут по кругу (от меньшего значения типа к большему). Это значит, что наш int c = 10000 прошли 1 раз от 0 до 127 (не поместились), 38 раз от -128 до 127 (не помещались), а на 39 кругу от -128 до 16 включительно. В этой статье объяснено получше, чем в этой лекции. https://vertex-academy.com/tutorials/ru/prividenie-tipov-v-java/
Антон Володин
26 уровень, Комсомольск-на-Амуре
5 ноября 2020, 13:24
Спасибо. Уже разобрался, но за ответ Спасибо!
Team Tiramisy
16 уровень
1 февраля, 12:17
лекции вообще сухо
Эндер Посол с красной планеты в четвёртом измерении
25 октября 2020, 11:50
А как быть с приведением к логическому типу данных (boolean)?
Pavel Miroshnichenko
12 уровень, Москва
6 октября 2020, 12:12
все приведения типов на рисунке компилятор кушает неявно. черные без потери старших битов, желтые с потерей. остальные нужно указывать явно. ps: Расширение это когда вы переменной большего размера присваиваете значение переменной меньшего размера (на рисунке расширение идет справа налево) вы пишете:
float f = 10000;
long l = (long) (f * f);
float f2 = l;
long l2 = (long) f2;
1) "При присваивании к float, происходит расширение типа. " Думаю, у int (коим является цифра 10000 в правой части присваивания) и переменной float одинаковый размер в памяти (4 байта). ТО есть расширения не происходит. Происходит автоматическое (неявное) приведение типов одинакового размера с потерей старших битов. (на рисунке желтая стрелка) 2) "При присваивании значения float к long, происходит сужение – необходимо приведение типа." Думаю, тут как раз происходит расширение, но так как float и long по разному хранят данные, то нужно делать явное приведение. поправьте если не прав, спасибо вообще вот хорошая статья https://metanit.com/java/tutorial/2.2.php на джавараш бывают хорошие статьи, но после этой, думаю, нужно еще что-то поискать...
Justinian Judge в Mega City OneMaster
20 октября 2020, 21:19
расширения не происходит.
происходит. Расширение кого/чего, расширение типов. Есть более обширный тип, есть более узкий. float содержит дробную часть и имеет диапазон больше чем int, значит он более общий тип. Байты, значения - не важно. А то получалось бы, есть long number = 1; int n = 500; 500 больше 1, значит расширения нет или в памяти, то что флоат занимает столько же памяти сколько и инт, нерелевантно учитывая совершенно разные принципы хранения, двоичное представление целого числа в инте и мантсса и показатель степени в вещественном типе.
JLS:
5.1.2. Widening Primitive Conversion
19 specific conversions on primitive types are called the widening primitive conversions:
    byte to short, int, long, float, or double
    short to int, long, float, or double
    char to int, long, float, or double
    int to long, float, or double
    long to float or double
    float to double
При присваивании значения float к long, происходит сужение – необходимо приведение типа."
Думаю, тут как раз происходит расширение, но так как float и long по разному хранят данные, то нужно делать явное приведение.
Как-бы его так запомнить... То что легко - можно без явного приведения. То что тяжело , с напрягом и само не сделается - нужно с явным приведением. От меньшего типа к большему - это легко, можно и без явного приведения. От более общего типа к менее, это напряжно, нужно явное приведение. Одеть более просторные штаны, это расширение, взял и одел, и забыл, все ок. Одеть на три размера меньше кожаные штаны или джины, это сужение, здесь нужно напрягаться, автоматом оно само не оденется, нужно явно задавать, это сужение. Еще раз, float и double, имеют дополнительную точность(запятая) и могут содержать астрономического порядка цифры, поэтому int, long будут всегда ниже в цепочке приведения типов.
Михаил Full Stack Developer в финтех
2 августа 2020, 16:06
2. При преобразовании из целых чисел в дробные могут отбрасываться самые младшие части числа. Но т.к. смысл дробного числа в том, чтобы хранить приблизительное значение, то такое присваивание разрешается.
Точно так? Если отбросить от целого числа младшие части, то получится ошибка на порядки. Похоже, что наоборот? Косноязычно написано, или я не так смысл понял?
Иван
31 уровень, Рязань
6 августа 2020, 09:20
Такой же вопрос, почему дробное число это приблизительное значение? наоборот же точное
OldTiredMan
14 уровень
20 августа 2020, 14:11
дробные числа точные только пока они в виде дроби целых чисел, например 1/3. а когда эта 1/3 представлена в виде 0.33333 - то это приблизительное значение, и его "точность" определяется количеством знаков после запятой. у флоата она поменьше, у дабла побольше.
Станислав
13 уровень, Санкт-Петербург
3 сентября 2020, 06:50
если я правильно понимаю, то число 123456 и число 0.12345 хранятся одинаково. То есть 12345 будет хранится как 12345, а его дробный аналог будет такой же только 12345(5) где последняя (5) - количество знаков после запятой. То есть оно будет требовать в любом случае на одну единицу памяти больше. Поэтому крайне большие целые числа, которые еле влезают в память для целых чисел, уже могут не поместиться в память для дробных.
Алиса
36 уровень, Санкт-Петербург
14 сентября 2020, 17:04
посмотрите в сторону "проблемы точности десятичных дробей в ЯП". есть прекрасные примеры того как x(= 0.2) * 0.3 != 0.6. связано это с тем, что x на самом деле равен условным 0.2000000001. Происходит так потому, что данные в большинстве ЯП хранятся не в десятичной системе.
Алиса
36 уровень, Санкт-Петербург
14 сентября 2020, 17:08
А конкретно в java хранится только 6-7 знаков после запятой, что и делает ее условно неточной. На тему java - личное мнение, основанное на предыдущей лекции)
27 сентября 2020, 12:51
ошибку на порядок вы как раз компенсируете степенью десятки, которая займет в значении место отброшенных младших разрядов. грубо говоря вместо 123456789 вы получите 1.234567*Е+08 (что равнозначно 123456700). Числа отличаются не на порядок, а всего лишь на 89, которые были отброшены от целого числа, чтобы освободить место для степени, а это 0,0007209%. Я написал чисто условно, чтобы наглядно показать, зачем отбрасывать младшие разряды и почему это уменьшает точность, но в принципе тут видно, что потери не так велики, чтобы о них переживать.
Ivan
18 уровень, Череповец
5 июня 2020, 14:42
Вот чего-то не хватало и я посмотрел три ролика на youtube и вроде как всё упаковалось в голове: Из двоичной в десятичную Из десятичной в двоичную Перевод чисел между системами счисления
Mao4ka SQL в есть такое место
16 июня 2020, 18:25
последнее видео очень интересное
Александр К.
11 уровень
29 августа 2020, 11:42
Спасибо за ссылки. Первые два интересные видео. Последнее - крайне занимательное 👍