Как преобразовать int в float с
Перейти к содержимому

Как преобразовать int в float с

  • автор:

Как преобразовать int в float с

При рассмотрении типов данных указывалось, какие значения может иметь тот или иной тип и сколько байт памяти он может занимать. В прошлой теме были расмотрены арифметические операции. Теперь применим операцию сложения к данным разных типов:

byte a = 4; int b = a + 70;

Результатом операции вполне справедливо является число 74, как и ожидается.

Но теперь попробуем применить сложение к двум объектам типа byte :

byte a = 4; byte b = a + 70; // ошибка

Здесь поменялся только тип переменной, которая получает результат сложения — с int на byte. Однако при попытке скомпилировать программу мы получим ошибку на этапе компиляции. И если мы работаем в Visual Studio, среда подчеркнет вторую строку красной волнистой линией, указывая, что в ней ошибка.

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

Дело в том, что операция сложения (да и вычитания) возвращает значение типа int, если в операции участвуют целочисленные типы данных с разрядностью меньше или равно int (то есть типы byte, short, int). Поэтому результатом операции a + 70 будет объект, который имеет длину в памяти 4 байта. Затем этот объект мы пытаемся присвоить переменной b, которая имеет тип byte и в памяти занимает 1 байт.

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

(тип_данных_в_который_надо_преобразовать)значение_для_преобразования;

Так, изменим предыдущий пример, применив операцию преобразования типов:

byte a = 4; byte b = (byte)(a + 70);

Сужающие и расширяющие преобразования

Преобразования могут быть сужающие (narrowing) и расширяющие (widening). Расширяющие преобразования расширяют размер объекта в памяти. Например:

byte a = 4; // 0000100 ushort b = a; // 000000000000100

В данном случае переменной типа ushort присваивается значение типа byte. Тип byte занимает 1 байт (8 бит), и значение переменной a в двоичном виде можно представить как:

00000100

Значение типа ushort занимает 2 байта (16 бит). И при присвоении переменной b значение переменной a расширяется до 2 байт

0000000000000100

То есть значение, которое занимает 8 бит, расширяется до 16 бит.

Сужающие преобразования, наоборот, сужают значение до типа меньшей разядности. Во втором листинге статьи мы как раз имели дело с сужающими преобразованиями:

ushort a = 4; byte b = (byte) a;

Здесь переменной b, которая занимает 8 бит, присваивается значение ushort, которое занимает 16 бит. То есть из 0000000000000100 получаем 00000100 . Таким образом, значение сужается с 16 бит (2 байт) до 8 бит (1 байт).

Явные и неявные преобразования

Неявные преобразования

В случае с расширяющими преобразованиями компилятор за нас выполнял все преобразования данных, то есть преобразования были неявными ( implicit conversion ). Такие преобразования не вызывают каких-то затруднений. Тем не менее стоит сказать пару слов об общей механике подобных преобразований.

Если производится преобразование от безнакового типа меньшей разрядности к безнаковому типу большой разрядности, то добавляются дополнительные биты, которые имеют значени 0. Это называется дополнение нулями или zero extension.

byte a = 4; // 0000100 ushort b = a; // 000000000000100

Если производится преобразование к знаковому типу, то битовое представление дополняется нулями, если число положительное, и единицами, если число отрицательное. Последний разряд числа содержит знаковый бит — 0 для положительных и 1 для отрицательных чисел. При расширении в добавленные разряды компируется знаковый бит.

Рассмотрим преобразование положительного числа:

sbyte a = 4; // 0000100 short b = a; // 000000000000100

Sing bit in conversions in c#

Преобразование отрицательного числа:

sbyte a = -4; // 1111100 short b = a; // 111111111111100

Sing bit negative number in conversions in c#

Явные преобразования

При явных преобразованиях ( explicit conversion ) мы сами должны применить операцию преобразования (операция () ). Суть операции преобразования типов состоит в том, что перед значением указывается в скобках тип, к которому надо привести данное значение:

int a = 4; int b = 6; byte c = (byte)(a+b);

Расширяющие преобразования от типа с меньшей разрядностью к типу с большей разрядностью компилятор проводит неявно. Это могут быть следующие цепочки преобразований:

byte -> short -> int -> long -> decimal

short -> float -> double

Все безопасные автоматические преобразования можно описать следующей таблицей:

В какие типы безопасно преобразуется

short, ushort, int, uint, long, ulong, float, double, decimal

short, int, long, float, double, decimal

int, long, float, double, decimal

int, uint, long, ulong, float, double, decimal

long, float, double, decimal

long, ulong, float, double, decimal

float, double, decimal

float, double, decimal

ushort, int, uint, long, ulong, float, double, decimal

В остальных случаях следует использовать явные преобразования типов.

Также следует отметить, что несмотря на то, что и double, и decimal могут хранить дробные данные, а decimal имеет большую разрядность, чем double, но все равно значение double нужно явно приводить к типу decimal:

double a = 4.0; decimal b = (decimal)a;

Потеря данных и ключевое слово checked

Рассмотрим другую ситуацию, что будет, например, в следующем случае:

int a = 33; int b = 600; byte c = (byte)(a+b); Console.WriteLine(c); // 121

Результатом будет число 121, так число 633 не попадает в допустимый диапазон для типа byte, и старшие биты будут усекаться. В итоге получится число 121. Поэтому при преобразованиях надо это учитывать. И мы в данном случае можем либо взять такие числа a и b, которые в сумме дадут число не больше 255, либо мы можем выбрать вместо byte другой тип данных, например, int.

Однако ситуации разные могут быть. Мы можем точно не знать, какие значения будут иметь числа a и b. И чтобы избежать подобных ситуаций, в c# имеется ключевое слово checked :

try < int a = 33; int b = 600; byte c = checked((byte)(a + b)); Console.WriteLine(c); >catch (OverflowException ex)

При использовании ключевого слова checked приложение выбрасывает исключение о переполнении. Поэтому для его обработки в данном случае используется конструкция try. catch. Подробнее данную конструкцию и обработку исключений мы рассмотрим позже, а пока надо знать, что в блок try мы включаем действия, в которых может потенциально возникнуть ошибка, а в блоке catch обрабатываем ошибку.

Как преобразовать int в float с

Если в арифметических операциях участвуют значения разных типов, то компилятор неявно пытается привести их к одному типу. Кроме того, когда мы присваиваем переменной какое-либо значение, это значение всегда приводится к типу переменной. Например:

char c = 6; int d = c;

Переменной d, которая представляет тип int, присваивается значение типа char, поэтому компилятор выполняет приведение значения от типа char к типу int.

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

Рассмотрим, какие преобразования применяет компилятор при арифметических операциях:

  1. Если один из операндов имеет тип long double , то второй операнд тоже будет преобразован в тип long double
  2. Если предыдущий пункт не выполняется и если один из операндов имеет тип double , то второй операнд тоже будет преобразован к типу double
  3. Если предыдущий пункт не выполняется и если один из операндов имеет тип float , то второй операнд тоже будет преобразован к типу float
  4. Если предыдущий пункт не выполняется и если один из операндов имеет тип unsigned long int , то второй операнд тоже будет преобразован к типу unsigned long int
  5. Если предыдущий пункт не выполняется и если один из операндов имеет тип long , то второй операнд тоже будет преобразован к типу long
  6. Если предыдущий пункт не выполняется и если один из операндов имеет тип unsigned , то второй операнд тоже будет преобразован к типу unsigned
  7. Если предыдущий пункт не выполняется то оба операнда приводятся к типу int
int a = 10; #include int main(void) < int number1 = 10; double number2 = 4; double result = number1 + number2; // 14.000000 printf("result = %f \n", result); // result = 14.000000 return 0; >

В выражении number1 + number2 число number2 представляет тип double , поэтому число number1 будет автоматически приводиться к числу double. И результат операции сложения также будет представлять тип double .

Операция преобразования

С помощью специальной операции преобразования мы можем явным образом привести данные к нужному типу. Например:

int a = 10; int b = 4; int c = a / b; // 2 double d = a / b; // 2.00000 double e = (double)a / (double)b; // 2.50000 printf("c = %d \n", c); printf("d = %f \n", d); printf("e = %f \n", e);

В выражении int c = a / b; результат деления будет целочисленный — 2, при котором дробная часть будет отброшена, так как оба операнда операции представляют целые числа.

В выражении double d = a / b; результат деления будет представлять вещественное число — 2.00000, но так как оба операнда являются целыми числами, то опять же результат операции будет представлять целое число 2, и только поле выполнения деления произойдет присвоение результата переменной d с приведением значения 2 от типа int к типу double.

В выражении double e = (double)a / (double)b применяется явное преобразование данных к типу double, поэтому и результат деления будет представлять вещественное число — 2.50000.

Для выполнения операции приведении в скобках указывается тот тип, к которому надо привести значение:

int number = 70; char symbol = (char) number; printf("symbol = %c \n", symbol); // F printf("symbol (int code) = %d \n", symbol); // 70

В ряде случаев преобразования сопровождаются потерей информации, например, когда числа большей разрядности (скажем размером 4 байт) получаем число меньшей разрядности (например, в 2 байта). Без потери информации проходят следующие цепочки преобразований:

char -> short -> int -> long

unsigned char -> unsigned short -> unsigned int -> unsigned long

float -> double -> long double

При всех остальных преобразованиях, которые не входят в эти цепочки, мы можем столкнуться с потерей точности данных. Так, в примере выше преобразование от int к char не является безопасным, поэтому к таким преобразованиям следует относиться с осторожностью. Например:

#include int main(void) < int number1 = 300; char code = number1; // потеря точности - число number1 усекается до 1 байта printf("code = %d \n", code); // code = 44 return 0; short number2 = 100000; // потеря точности - число 100000 усекается до 2 байт printf("number2 = %d \n", number2); // number2 = -31072 >

Здесь две ситуации небезопасных преобразований. В первом случае число типа int , которое равно 300, присваивается переменной типа char . В итоге переменная code будет равна 44. Почему? Число 300 в двоичной системе:

0000000100101100

Оставляем только первый младший байт:

00101100

И у нас получается число 44 в десятичной системе.

Во втором случае число 100000 (которое по умолчанию представляет тип int ), усекается до разрядности типа short — до двух байт.

short number = 100000;

В итоге число number в реальности будет равно -31072.

Преобразование float в int с инициализацией переменной на лету, адекватно?

Каким путем? У вас не ясно какой тип у x.
Видимо подразумевается, что x — int.
Выражение 2 * (a + y) в итоге имеет тип float.
Если x — int, то выражение будет преобразовано к int.
Правильно отбрасывать дробную часть или нет — зависит от задачи.
Если надо — отбрасывайте. Предложенный способ — вполне годный.
В любом случае лучше использовать явное преобразование. Это поможет людям, которые будут смотреть ваш код, понять, что это преобразование именно так и задумывалось, а не получилось случайно.

Рекомендую поставить опции компилятора на максимальные предупреждения и соответствия стандарту (для gcc -std=c11 -Wall -Wextra -pedantic) и пишите код так, что бы при сборке у компилятора не было предупреждений. Многие используют еще и -Werror — это прост вынуждает вас писать код без предупреждений, т.к. они теперь станут ошибками.

Преобразование int в float

Число float состоит из 1 бита знака, 8 бит экспоненты и 23 бит мантиссы.
Бинарное представление 20110511:
0000 0001 0011 0010 1101 1100 1010 1111
Видно, что 24-й бит равен 1, где находятся биты экспоненты.
При более 6 цифр в значение x число отображается с учётом экспоненты.
Как решить проблему?

94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
Ответы с готовыми решениями:

Как происходит преобразование int
Как происходит преобразование int<<float<int int n=222222222; float f=(float)n; n=(int)f;.

ОШИБКА [Error] cannot convert ‘int*’ to ‘float*’ for argument ‘1’ to ‘void Syma(float*,int*,int)
Какая то проблема с указателями,незнаю,не хочет щитать суму парних чисел в второй.

Преобразование int в float (битовый перенос)
Ребят, нигде в интернете не нашел ответа Битовые сдвиги с float не работают Нужно побитово.

Функции float average(int arrray[],int from,int to)
Напишите код функции float average(int arrray,int from,int to). Возвращаемым значением функции.

541 / 446 / 162
Регистрация: 10.12.2009
Сообщений: 1,857
попробуй так:

std::cout  (int)a  std::endl;

return (true);
1976 / 1111 / 221
Регистрация: 19.04.2011
Сообщений: 2,345

ЦитатаСообщение от alexsvk Посмотреть сообщение

При более 6 цифр в значение x число отображается с учётом экспоненты.
Как решить проблему?
Использовать FormatFloat() как вам надо

coutx' ' FormatFloat("0.0000",a).c_str() endl;

Эксперт С++

1068 / 847 / 60
Регистрация: 30.04.2011
Сообщений: 1,659
Народ! Вы чего, совсем книжек не читаете?
Блин, читайте манипуляторы и конкретно setprecision()
Регистрация: 18.03.2011
Сообщений: 19

alexsvk, а что вас, собственно, не устраивает? Все правильно выводит, только погрешность 11 присутствует, но это наверно исправится если использовать SetPrecision.

Число float состоит из 1 бита знака, 8 бит экспоненты и 23 бит мантиссы.
Бинарное представление 20110511:
0000 0001 0011 0010 1101 1100 1010 1111
Видно, что 24-й бит равен 1, где находятся биты экспоненты.
При более 6 цифр в значение x число отображается с учётом экспоненты.

Ну как бы при выводе и присваивании переменной типа double она будет выводится и присваиваться как double. Если вам надо проинтерпретировать 4 байта памяти, в которых хранится целое x, как float, то надо написать примерно следующее:
int x=2;
float* pf=(float*)&x;
float a=*pf;

Регистрация: 15.07.2010
Сообщений: 255

ЦитатаСообщение от lega4 Посмотреть сообщение

alexsvk, а что вас, собственно, не устраивает? Все правильно выводит, только погрешность 11 присутствует, но это наверно исправится если использовать SetPrecision.

Ну как бы при выводе и присваивании переменной типа double она будет выводится и присваиваться как double. Если вам надо проинтерпретировать 4 байта памяти, в которых хранится целое x, как float, то надо написать примерно следующее:
int x=2;
float* pf=(float*)&x;
float a=*pf;

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *