Перейти к содержимому

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

  • автор:

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

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

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

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

Чето не могу найти нормального решения, которое было бы быстрее чем стандарные.
Я делаю так:

int i; float f=5.68; i=(int)f;

Возможно ли более быстро сделать данное преобразование?
Просто вычисления с float’ом работают раза в 2 медленнее чем с int’ом, а точность большая не нужна.
Дело в том что напрягает загрузка процессора, т.к. это дело в многократно вызываемом цикле.
Может есть какой-нить алгоритм на асме пошустрее? Или может какой-нить совет по настройкам оптимизации проекта. Интересны все предложения.
И ещё вопрос:
Что быстрее

a=i*256;

Re: Подскажите как быстро преобразовать float в int.

От: Socrat
Дата: 29.06.06 10:19
Оценка:

Здравствуйте, Voit, Вы писали:

V>Чето не могу найти нормального решения, которое было бы быстрее чем стандарные.
V>Я делаю так:

V>

V>int i; V>float f=5.68; V>i=(int)f; V>

V>Возможно ли более быстро сделать данное преобразование?

Нельзя. Если даже ты не используешь сопроцессор, вряд ли ты сможешь написать преобразование более быстрое, чем уже есть.

V>Просто вычисления с float’ом работают раза в 2 медленнее чем с int’ом, а точность большая не нужна.
V>Дело в том что напрягает загрузка процессора, т.к. это дело в многократно вызываемом цикле.

Можно попробовать обойтись без плавающей точки.

V>Может есть какой-нить алгоритм на асме пошустрее? Или может какой-нить совет по настройкам оптимизации проекта. Интересны все предложения.
V>И ещё вопрос:
V>Что быстрее

V>a=i*256; V>
V>a=i>>8; V>

Сдвиг быстрей. Только не туда двигаешь.

Re[2]: Подскажите как быстро преобразовать float в int.

От: Сергей Мухин
Дата: 29.06.06 10:35
Оценка: +1 -1

Здравствуйте, Socrat, Вы писали:

V>>Что быстрее

V>>

V>>a=i*256; V>>
V>>a=i>>8; V>>

с какого испуга?

посмотри генерацию (при вкл оптим).


С уважением,
Сергей Мухин
Re: Подскажите как быстро преобразовать float в int.

От: Какая разница
Дата: 29.06.06 10:42
Оценка:

Здравствуйте, Voit, Вы писали:

V>Чето не могу найти нормального решения, которое было бы быстрее чем стандарные.
V>Я делаю так:

V>

V>int i; V>float f=5.68; V>i=(int)f; V>

V>Возможно ли более быстро сделать данное преобразование?

Откуда уверенность что это самое узкое место в твоей программе?
Что тебе даст выиграш нескольких тактов процессора если ты умудришся
на асме запрограмировать быстрее чем компалятор?
Сомневаюсь что сможешь это сделать лучше
Сначала надо взять профилер в зубы и найти в программе те куски которые дают наибольшие тормоза
Поверь мне это будет не это преобразование

ЗЫ Ну и неплохо было бы преобразовать в инт поинтелегентней (по правилам округления)

i=(int) (f + 0.5f);

Re: Подскажите как быстро преобразовать float в int.

От: Какая разница
Дата: 29.06.06 10:50
Оценка:

Здравствуйте, Voit, Вы писали:
.
V>И ещё вопрос:
V>Что быстрее

V>a=i*256; V>
V>a=i>>8; V>

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

ЗЫ Причем сдвинет влево а не вправо как ты

Re: Подскажите как быстро преобразовать float в int.

От: Sh1ZoID http://vkontakte.ru/id6263850
Дата: 29.06.06 11:08
Оценка:

Здравствуйте, Voit, Вы писали:

V>Что быстрее

V>a=i*256; V>
V>a=i>>8; V>

int i = 23;
int c = i c = i * 255; //255

 ;int i = 23; 0041368E mov dword ptr [i],17h ;int c = i mov eax,dword ptr [i] 00413698 shl eax,8 ;смещает 0041369B mov dword ptr [c],eax ;c = i * 255; 0041369E mov eax,dword ptr [i] 004136A1 imul eax,eax,0FFh ;умножает 004136A7 mov dword ptr [c],eax

int i = 23;
int c = i c = i * 256; //256

 ;int i = 23; 0041368E mov dword ptr [i],17h ;int c = i mov eax,dword ptr [i] 00413698 shl eax,8 ;смещает 0041369B mov dword ptr [c],eax ;c = i * 255; 0041369E mov eax,dword ptr [i] 004136A1 shl eax,8 ;смещает 004136A7 mov dword ptr [c],eax

В теории(и ессно, если на асме пишешь), конечно разница есть(сдвиг быстрее), но на практике чаще нет, чем да. Так что умножай на здоровье

Re: Подскажите как быстро преобразовать float в int.

От: Leo Yuriev https://github.com/erthink
Дата: 29.06.06 11:13
Оценка: 1 (1) +1

Здравствуйте, Voit, Вы писали:

V>Чето не могу найти нормального решения, которое было бы быстрее чем стандарные.
V>Я делаю так:

V>

V>int i; V>float f=5.68; V>i=(int)f; V>

V>Возможно ли более быстро сделать данное преобразование?
V>Просто вычисления с float’ом работают раза в 2 медленнее чем с int’ом, а точность большая не нужна.
V>Дело в том что напрягает загрузка процессора, т.к. это дело в многократно вызываемом цикле.
V>Может есть какой-нить алгоритм на асме пошустрее? Или может какой-нить совет по настройкам оптимизации проекта. Интересны все предложения.
Сильно зависит от вида процессора, на x86 процессор имеет команду сохраниния float в int, при этом автоматически и бысто делает округление к ближайщему целому. Но по правилам C/C++ преобразование float в int должно выполняться с усечением. Поэтому i=(int)f выполняется отдельной библиотечной функцией, которая сохраняет режим FPU, меняет его режим округления на уселечение, сохраняет float в int и восстанавливает режим FPU. Сделать быстрее можно только через inline-assembler (будет равносильно i=(int)(f + .5)). Синтаксис зависит от компилятора, см. команды fld, fistp и fist.

V>И ещё вопрос:
V>Что быстрее

V>a=i*256; V>
V>a=i>>8; V>

Re[2]: Подскажите как быстро преобразовать float в int.

От: Voit
Дата: 29.06.06 11:29
Оценка:

Здравствуйте, Leo Yuriev, Вы писали:

LY>Здравствуйте, Voit, Вы писали:

V>>Чето не могу найти нормального решения, которое было бы быстрее чем стандарные.
V>>Я делаю так:

V>>

V>>int i; V>>float f=5.68; V>>i=(int)f; V>>

V>>Возможно ли более быстро сделать данное преобразование?
V>>Просто вычисления с float’ом работают раза в 2 медленнее чем с int’ом, а точность большая не нужна.
V>>Дело в том что напрягает загрузка процессора, т.к. это дело в многократно вызываемом цикле.
V>>Может есть какой-нить алгоритм на асме пошустрее? Или может какой-нить совет по настройкам оптимизации проекта. Интересны все предложения.
LY>Сильно зависит от вида процессора, на x86 процессор имеет команду сохраниния float в int, при этом автоматически и бысто делает округление к ближайщему целому. Но по правилам C/C++ преобразование float в int должно выполняться с усечением. Поэтому i=(int)f выполняется отдельной библиотечной функцией, которая сохраняет режим FPU, меняет его режим округления на уселечение, сохраняет float в int и восстанавливает режим FPU. Сделать быстрее можно только через inline-assembler (будет равносильно i=(int)(f + .5)). Синтаксис зависит от компилятора, см. команды fld, fistp и fist.

V>>И ещё вопрос:
V>>Что быстрее

V>>a=i*256; V>>
V>>a=i>>8; V>>

Re[3]: Подскажите как быстро преобразовать float в int.

От: ned
Дата: 29.06.06 11:46
Оценка:

Здравствуйте, Сергей Мухин, Вы писали:

S>>Сдвиг быстрей.

СМ>с какого испуга?

СМ>посмотри генерацию (при вкл оптим).

Так, так. Какой компилятор, платформа?
У меня в обоих случаях компилятор генерит сдвиг.
Команда shl выполнятся всего несколько тактов, а mul намного дольше.

Re[4]: Подскажите как быстро преобразовать float в int.

От: Sh1ZoID http://vkontakte.ru/id6263850
Дата: 29.06.06 11:59
Оценка:

Здравствуйте, ned, Вы писали:

ned>Здравствуйте, Сергей Мухин, Вы писали:

S>>>Сдвиг быстрей.

СМ>>с какого испуга?

СМ>>посмотри генерацию (при вкл оптим).

ned>У меня в обоих случаях компилятор генерит сдвиг.

Дык о том и речь

Re: Подскажите как быстро преобразовать float в int.

От: vvotan
Дата: 29.06.06 13:03
Оценка:

Здравствуйте, Voit, Вы писали:

V>Возможно ли более быстро сделать данное преобразование?

Преобразования типов с плавающей запятой

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

При преобразовании значения с плавающей запятой в целочисленный тип оно сначала усекается путем удаления дробной части. Если усеченное значение может быть представлено в результирующем типе, результатом должно быть это значение. Если значение не может быть представлено, результат не определен.

Блок, относящийся только к системам Microsoft

Компиляторы Майкрософт используют представление binary32 согласно IEEE-754 для значений типа float и представление binary64 для long double и double . Так как для long double и double используется одно и то же представление, они имеют одинаковый диапазон и точность.

Когда компилятор преобразует число типа double или long double с плавающей запятой в значение float , он округляет результат в соответствии с элементами управления среды с плавающей запятой, значение по умолчанию которых — «округлить до ближайшего числа с привязкой к четному». Если числовое значение слишком велико или слишком мало для представления в виде числового значения float , результат преобразования будет положительной или отрицательной бесконечностью в соответствии со знаком исходного значения, и возникает исключение переполнения, если оно включено.

Для преобразования в целочисленный тип меньше long сначала значение преобразуется в тип long , а затем в результирующий тип.

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

  • Результатом может быть значение-метка, то есть представимое значение, максимально удаленное от нуля. Для типов со знаком это наименьшее представимое значение (0x800. 0). Для типов без знака это наибольшее представимое значение (0xFF. F).
  • Результат может дополняться, то есть значение, которое слишком велико для представления, преобразуется в наибольшее представимое значение, а значение, которое слишком мало для представления, преобразуется в наименьшее представимое значение. Одно из этих двух значений также используется в качестве значения-метки.
  • При преобразовании в тип unsigned long или unsigned long long значения, выходящего за пределы соответствующего диапазона, результатом может быть некоторое значение, отличающееся от наибольшего или наименьшего представимого. Будет ли результат значением-меткой, дополненным значением или ни тем ни другим, зависит от параметров компилятора и целевой архитектуры. В будущих версиях компилятора может возвращаться дополненное значение или значение-метка, даже если в предыдущих версиях оно не возвращалось.

Завершение блока, относящегося только к системам Майкрософт

В следующей таблице перечислены преобразования из типов с плавающей запятой.

Таблица преобразования типов с плавающей запятой

Исходный тип Кому Метод
float char Преобразование в long , затем преобразование long в char
float short Преобразование в long , затем преобразование long в short
float int Усечение до десятичной запятой. Если результат слишком велик для представления в качестве значения int , результат не определен.
float long Усечение до десятичной запятой. Если результат слишком велик для представления в качестве значения long , результат не определен.
float long long Усечение до десятичной запятой. Если результат слишком велик для представления в качестве значения long long , результат не определен.
float unsigned char Преобразование в long , затем преобразование long в unsigned char
float unsigned short Преобразование в long , затем преобразование long в unsigned short
float unsigned Усечение до десятичной запятой. Если результат слишком велик для представления в качестве значения unsigned , результат не определен.
float unsigned long Усечение до десятичной запятой. Если результат слишком велик для представления в качестве значения unsigned long , результат не определен.
float unsigned long long Усечение до десятичной запятой. Если результат слишком велик для представления в качестве значения unsigned long long , результат не определен.
float double Представление в качестве значения double .
float long double Представление в качестве значения long double . В MSVC long double и double имеют одно и то же представление.
double char Преобразование в float , затем преобразование float в char
double short Преобразование в float , затем преобразование float в short
double int Усечение до десятичной запятой. Если результат слишком велик для представления в качестве значения int , результат не определен.
double long Усечение до десятичной запятой. Если результат слишком велик для представления в качестве значения long , результат не определен.
double unsigned char Преобразование в long , затем преобразование long в unsigned char
double unsigned short Преобразование в long , затем преобразование long в unsigned short
double unsigned Усечение до десятичной запятой. Если результат слишком велик для представления в качестве значения unsigned , результат не определен.
double unsigned long Усечение до десятичной запятой. Если результат слишком велик для представления в качестве значения unsigned long , результат не определен.
double unsigned long long Усечение до десятичной запятой. Если результат слишком велик для представления в качестве значения unsigned long long , результат не определен.
double float Представление в качестве значения float . Если значение double невозможно точно представить с типом float , происходит потеря точности.
double long double Значение long double рассматривается как double .

Преобразования из типа long double производятся так же, как из типа double .

Явное и неявное преобразование типов данных C++

В C++ различают явное и неявное преобразование типов данных. Неявное преобразование типов данных выполняет компилятор С++, ну а явное преобразование данных выполняет сам программист. О преобразовании типов данных скажу следующее: «Результат любого вычисления будет преобразовываться к наиболее точному типу данных, из тех типов данных, которые участвуют в вычислении». Для наглядного примера представлю таблицу с преобразованиями типов данных. В таблице рассмотрим операцию деления. В качестве целочисленного типа данных возьмем int, ну и вещественный тип данных у нас будет float.

Таблица 1 — Явное и неявное преобразование типов данных в С++

x y Результат деления Пример
делимое делитель частное x = 15 y = 2
int int int 15/2=7
int float float 15/2=7.5
float int float 15/2=7.5

Из таблицы видно, что меняя переменные различных типов данных местами, результат остается тот же (в нашем случае это делимое и делитель). О неявном преобразовании типов данных все. Что же касается явного преобразования, то оно необходимо для того чтобы выполнять некоторые манипуляции, тем самым меняя результат вычисления. Самый простой способ явного преобразования типов данных, пример: допустим нам необходимо разделить такие числа 15 и 2, делим! 15/2=7 . Результат тот же, что и в таблице. Но если сделать незначительные преобразования, например: 15.0/2=7.5 при таком делении число 15 является вещественным, значит и результат будет вещественный. Само число 15 с точки зрения математики не изменилось, ведь 15=15.0. Этот же прием можно было применить к двойке, результат был бы тем же, а можно было сразу к двум числам, но зачем ,если хватает одного из двух.

Еще один способ явного преобразования типов данных:

float(15) / 2 // результат равен 7.5, число 15 преобразуется в вещественный тип данных float. double(15) / 2 // результат равен 7.5 – тоже самое.

В С++ также предусмотрена унарная операция приведения типа:

static_cast(/*переменная или число*/)

пример: static_cast(15)/2 результат равен 7.5
Пример с переменной:

int ret=15; static_cast(ret)/2 //результат равен 7.5

В случае с переменной надо понимать, что в строке 2 переменная ret не преобразуется в тип данных float , а всего лишь на всего создается временная копия переменной ret с типом данных float . Рассмотрим на практике все способы явного и неявного преобразования типов данных.

// pryeobrazovanie.cpp: определяет точку входа для консольного приложения. #include "stdafx.h" #include #include using namespace std; int _tmain(int argc, _TCHAR* argv[]) < int int_value15 = 15, int_value2 = 2; // объявляем две переменные типа int float float_value15 = 15, float_value2 = 2; // объявляем две переменные типа float cout (15) / 2 = " (15) / 2 (15) = " (15) (20) = " (20) 

В строке 5 подключена библиотека манипуляций ввода/вывода , эта библиотека нужна для использования различных манипуляторов, в нашем случае — fixed setprecision() . В строке 10 специально создал две переменные типа int , аналогично создал две переменный типа float в строке 11 , эти переменные нужны будут для преобразования их значений в другие типы данных. В строке 12 после оператора cout и операции сдвига в поток вывода и setprecision() . Манипулятор fixed — это не параметризированный манипулятор, так как никаких параметров не принимает, пишется без круглых скобок. Данный манипулятор применяется в паре с параметризированным манипулятором setprecision() и выполняет фиксированное отображение разрядов после запятой. А манипулятор setprecision() отображает количество знаков после запятой, причём то, которое указано в скобочках. В строках 13, 14, 15, 16 показаны примеры неявного преобразования типов данных, эти примеры взяты из таблицы 1 . В строках 17, 18 показан один из способов явного преобразования данных. Суть такого способа заключается в том, что нужно дописать запятую и нуль к целому числу. В строках 19, 20 явное преобразование выполняется посредством использования приводимых типов как функций, внутри скобочек которых, нужно указать значение или переменную, которую необходимо преобразовать. В строках 21, 22, 23 выполняется явное преобразование типов данных с помощью унарной операции преобразования данных. В круглых скобочках указывается, переменная или значение, которое нужно преобразовать, а в обрамлении знаков < >тип данных, к которому нужно преобразовать. Пример работы программы показан ниже (см. Рисунок 1).

Явное и неявное преобразование типов данных в C++

Рисунок 1 — Явное и неявное преобразование типов данных C++

В строках 22, 23 выполняется унарная операция преобразования данных, причём преобразуются числа 15 и 20 к типу данных char . Этот тип данных пока вам не известен, но запомните, что char — тип данных для хранения символов. Так вот, из рисунка 1 видно, что в конце появились символы. Эти символы получились путём преобразования чисел в char . Числами являлись коды из таблицы ASCII. Таким образом, если необходимо вывести какой-нибудь символ из таблицы ASCII, это можно сделать как показано в строках 22, 23, при этом подставив только нужный код.

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

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