Как перевести float в int
C Урок 14. Преобразование типов
На данном уроке мы поговорим о преобразовании типов данных в процессе работы программы из одного типа в другой.
Конечно, в идеальном случае, желательно, чтобы программа была построена таким образом чтобы лишний раз избегать всякого рода преобразований и использовать везде данные нужного типа. Но не всегда так получается и преобразование типа в ряде случаев просто необходимо. Например, мы складываем значения двух переменных типа unsigned short и, по идее у нас результат тоже должен присваиваться переменной типа unsigned short. Но мы не уверены в том, что этот результат уместится в такой тип, например, мы захотим сложить числа 65535 и 65534. Поэтому здесь без преобразования не обойтись. И таких ситуаций огромное множество, поэтому мы должны знать как происходит преобразование типов автоматически, а также как мы можем этим процессом управлять. Думаю, данный урок даст хоть и не полную картину преобразований типов, но, тем не менее, внесёт некоторую ясность в данную тему.
Для начала давайте начнём с автоматического преобразования типов, или, если это правильно назвать, с неявного приведения типов. В данном случае преобразованием типов будет управлять компилятор и мы никаких специальных операций для данного преобразования не применяем.
Если операнды некоторой операции принадлежат различным типам, то они автоматически приводятся к определённому общему типу. А к какому именно, существует ряд правил.
Также надо учесть, что автоматические преобразования типов имеют место лишь в тех случаях, когда они не влекут потери данных и при этом превращают операнды с меньшим диапазоном значений в операнды с большим диапазоном. Например, если мы складываем операнд целого типа с операндом с плавающей точкой, то первый автоматически приведётся к типу с плавающей точкой. Или, если мы складываем операнд типа int с оператором типа short, то второй автоматически превратится в число типа int, так как у него больший диапазон значений. Тем самым достигается принцип целостности информации. Если же результат наших операций мы попытаемся присвоить переменной такого типа, у которого меньший диапазон значений, то мы рискуем потерять часть информации, хотя при этом код все равно соберётся и мы получим лишь предупреждение.
Также неявное преобразование операндов какой-либо операции происходит в том случае, когда от этой операции есть смысл. А если мы, к примеру, захотим использовать тип с плавающей точкой в качестве номера элемента массива, то в таком случае мы уже получим ошибку.
Для того, чтобы заранее знать, какой общий тип мы получим при операции с разными типами данных, существует приоритет типов данных для операций преобразований типов. Вот перечень типов данных с убывающим приоритетом при операциях неявного приведения типов
Если в операции присутствуют операнды различных типов то компилятор вычисляет сначала операнд наивысшим приоритетом и неявно преобразовывает тип другого операнда, у которого приоритет ниже, к типу первого.
В операциях присваивания также может происходить неявное преобразование типов данных.
Например, если мы хотим значение 8-байтового типа присвоить переменной 4-байтового типа, неважно, целого типа эти данные или нет, то при этом произойдёт неявное преобразование к 4-байтовому типу, при этом старшие 4 байта отбрасываются. Это считается небезопасным приведением типов, когда возможна потеря информации.
Может быть и наоборот, если мы хотим значение 4-байтового типа присвоить переменной 8-байтового типа. Также произойдёт неявное преобразование и, наоборот, 4 старших байта добавятся и заполнятся нулями. Это будет уже безопасное приведение типа и при этом целостность информации не страдает.
Так как мы с указателями ещё не работали, то в данном уроке мы их преобразование рассматривать не будем, скажу лишь, что там всё происходит аналогично, разница в поведении указателей типа void.
Думаю, что теперь ситуация с неявным преобразованием типов теперь немного стала понятна, конечно же, полное понимание придёт лишь с практикой.
Явное преобразование типов происходит тогда, когда мы применяем специальные механизмы для приведения одного типа к строго определённому другому типу. В языке C в для явного приведения типа перед переменной или выражением, значения которых мы преобразуем к другому типу, ставится в круглых скобках тип, к которому мы данное значение преобразуем, например
int i;
char c = 45;
i = ( int )c;
В данном случае значение переменной c явно преобразовывается к типу данных int, а затем уже в преобразованном виде присваивается переменной i.
Вот ещё несколько примеров явного преобразования типов данных
Давайте теперь поэкспериментируем с преобразованием типов данных на практике в реальном коде.
Проект сделаем из проекта MYPROG13 прошлого занятия и имя ему было присвоено MYPROG14.
Откроем файл main.c и в функции main(), как обычно, удалим весь код тела кроме возврата нуля, останется от него вот это
int main()
return 0 ; //Return an integer from a function
Удалим также вот эти константы
#define VAR_CONST1 12345
#define HELLO_CONST «\»Hello, world. \»»
Добавим в тело функции main() следующий код
Как правильно преобразовать тип float в int и наоборот?
Приведенный ниже код выполняет быструю операцию обратного извлечения квадратного корня с помощью некоторых битовых хаков. Вероятно, алгоритм был разработан Silicon Graphics в начале 1990-х годов, а также появился в Quake 3. дополнительная информация
Однако я получаю следующее предупреждение от компилятора GCC C ++ : разыменование указателя с перетеканием типа нарушит правила строгого псевдонима
8 ответов
Основываясь на ответах здесь, я создал современную функцию «псевдоприведения» для простоты применения.
Версия C99 (хотя большинство компиляторов поддерживают это, теоретически в некоторых может быть неопределенное поведение)
Универсальные версии (на основе принятого ответа)
Типы отливок одинакового размера:
Типы отливок любых размеров:
Используйте это как:
Обновление для C ++ 20
Приведение вызывает неопределенное поведение. Независимо от того, какую форму приведения вы используете, это все равно будет неопределенным поведением. Он не определен независимо от того, какой тип приведения вы используете.
Большинство компиляторов будут делать то, что вы ожидаете, но gcc любит быть злым и, вероятно, будет предполагать, что вы не назначили указатели, несмотря на все ваши указания, и изменит порядок операции, чтобы они давали какой-то странный результат.
Если у вас есть доступ к C ++ 20 или более поздней версии, вы можете использовать std::bit_cast
Обновить
Я больше не считаю этот ответ правильным из-за обратной связи, которую я получил от комитета. Но я хочу оставить это в информационных целях. И я целенаправленно надеюсь, что этот ответ может быть исправлен комитетом (если он захочет это сделать). Т.е. В базовом оборудовании нет ничего, что могло бы сделать этот ответ неверным, это просто мнение комитета, которое делает это или нет.
Я добавляю ответ не для опровержения принятого ответа, а для его дополнения. Я считаю, что принятый ответ правильный и эффективный (и я только что проголосовал за него). Однако я хотел продемонстрировать другую технику, столь же правильную и эффективную:
Здесь есть несколько хороших ответов, которые касаются проблемы набора текста.
Я хочу обратиться к части «быстрого вычисления обратного квадратного корня». Не используйте этот «трюк» на современных процессорах. Каждый основной вектор ISA имеет специальную аппаратную инструкцию для быстрого вычисления обратного квадратного корня. Каждый из них и быстрее, и точнее, чем этот часто копируемый небольшой взлом.
Преобразования типов с плавающей запятой
Если значение с плавающей запятой преобразуется в другой тип с плавающей запятой и при этом может быть точно представлено в результирующем типе, оно не изменяется. Если исходное значение является числовым, но при этом не может быть представлено точно, результатом будет следующее более высокое или низкое значение, которое может быть представлено. Диапазон типов с плавающей запятой см. в разделе Ограничения констант с плавающей запятой.
При преобразовании значения с плавающей запятой в целочисленный тип оно сначала усекается путем удаления дробной части. Если усеченное значение может быть представлено в результирующем типе, результатом должно быть это значение. Если значение не может быть представлено, результат не определен.
Блок, относящийся только к системам Microsoft
При преобразовании в целочисленные типы не меньше long для значения, которое слишком велико или слишком мало для представления в результирующем типе, может возвращаться любое из следующих значений:
Результатом может быть значение-метка, то есть представимое значение, максимально удаленное от нуля. Для типов со знаком это наименьшее представимое значение (0x800. 0). Для типов без знака это наибольшее представимое значение (0xFF. F).
Результат может дополняться, то есть значение, которое слишком велико для представления, преобразуется в наибольшее представимое значение, а значение, которое слишком мало для представления, преобразуются в наименьшее представимое значение. Одно из этих двух значений также используется в качестве значения-метки.
При преобразовании в тип unsigned long или unsigned long long значения, выходящего за пределы соответствующего диапазона, результатом может быть некоторое значение, отличающееся от наибольшего или наименьшего представимого. Будет ли результат значением-меткой, дополненным значением или ни тем ни другим, зависит от параметров компилятора и целевой архитектуры. В будущих версиях компилятора может возвращаться дополненное значение или значение-метка, даже если в предыдущих версиях оно не возвращалось.
Завершение блока, относящегося только к системам Майкрософт
В следующей таблице перечислены преобразования из типов с плавающей запятой.
Таблица преобразования типов с плавающей запятой
Sidebar
Search this site
Categories
Latest
Converting float to int in C
In this post, we’ll see how to convert a float to an int in C. We’ll assume both int and float datatypes to be 32-bits long an int using two’s complement representation for negative values. The conversion will be performed using the bit-level representation of the float data type. Only addition, subtraction, and bitwise operations will be used.
This is also a solution for exercise 2.96 of the Computer Systems: A Programmer’s Perspective book.
Rounding to whole numbers
For positive values, we round down:
Negative values are rounded up:
In practical terms, the fractionary part is truncated.
Getting the floating-point fields
The floating-point single-precision data representation ( float ), consists of three different fields.
These fields are used to encode a number in the form:
For our converter, we’ll start by getting these different fields.
They are obtained by shifting operations combined with masks to get the necessary bits. On the code snippet above, f contains the 32-bit float representation of the value.
Special cases: NaN and Infinity
Floating-point encodes special values such as NaN (not a number, obtained by expressions such as sqrt(-1) or 0.0 / 0.0 ) and infinity (for values that overflow) with the exp field all set to ones. For these special cases, we’ll return the special value 0x80000000 (which corresponds to INT_MIN ).
Denormalized values
Denormalized values are those in which the exp field is all zeros. In floating-point representation, they are used to encode values that are very close to zero (both positive and negative). All of these values will be rounded to zero.
Normalized values
Finally, we can focus on normalized values. In this case, the exp field is neither all ones nor all zeros. For this group of values, the exponent E is encoded as:
Where exp is the unsigned 8-bit number represented by the exp field and Bias = 127. We can get the exponent E as follows:
Values less than one
Where XXX represents the fractionary part of the magnificand, encoded by the frac field. 0.1XXX is a binary fraction less than one.
Overflowing
The int datatype represents numbers using 31 bits (the remaining bit is used for the sign). This means that the binary representation of our value can be at most 31 bits long. This limit case will take place when E = 30 :
X. X are the 23 bits of the frac field. The value 1X. X0. 0 will be 31 bits long: a leading one + 23 frac bits + 7 zeros.
We can conclude that float will overflow when E > 30 :
Normalized values in the range of int
Finally, we’re left with the float values that can be rounded to an int other than zero and that won’t overflow.
The frac field is 23 bits long. Remember that the exponent E and frac encode a value in the form:
Where each X is one of the 23 binary digits of the frac field. They represent the digits that come after the binary point (fractionary part).
A positive value of E will shift the binary point E places to the right. For instance if E = 2 :
Here we’re using the symbol Y for the 21 frac binary digits that come after the binary point.
On the other hand, if E is larger than 23, the binary point will be shifted beyond the bits of the frac field and we’ll have extra zeros to the right:
Here x is the resulting bit-level int representation. First, we shift the leading one E places to the left. Then, we get the integer part of the float value by shifting operations as it was mentioned above. Note that we use the bitwise OR operator ( | ) as a way of “adding” the leading one and the lower order bits of the frac field (e.g. 100 | 001 = 101 ).
Negative values
Finally, we modify the bit encoding for negative values.
Complete program and testing
Putting all of the pieces together in the float_f2i function, we get:
Testing
The program was tested as follows:
We used the variable bits to generate all the possible bit-level combinations. The address of bits was then referenced as datatypes float and float_bits to perform the test. Finally, we verified that the result of casting float to int was the same as the return value of the float_f2i function.
When compiled, we received no error output which means that the converter worked for all of the tested values.
Convert Float to Int [closed]
Want to improve this question? Add details and clarify the problem by editing this post.
So I’ve got a project I’m working on. This is the only error I have:
Cannot implicitly convert type ‘float’ to ‘int’.
I understand somewhat what that means. I just need help converting my float to int.
This is just an example of one of the floats:
Here’s the specific code section:
2 Answers 2
When converting between integers ( int ) and floating-point ( float ) numbers, you can do this:
But you can’t do this:
The reason the first conversion is possible, is that converting the integer number ( int ) to a floating-point number ( float ) does not change the number. It is a safe conversion, and therefore can be done implicitly.
The reason the second conversion is not allowed, is that converting the floating-point number (which may have a fractional part) to an integer number (that never has a fractional part) must drop the fractional part of the number, i.e. it becomes a different number. This is not safe, and can therefore only be done explicitly.
To explicitly convert one type of number to another, you use a cast. That’s the parentheses before the number with the type of the number that you want to convert it to.
Latest









