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

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

  • автор:

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

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

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

Блок, относящийся только к системам 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 .

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

batur вне форума

По умолчаниюПреобразование из float в int

Привет всем, есть вопрос в плане передачи переменной int с пр200 на пк через преобразователь где установлена будет скада, пока не знаю что за версия.
например нужно мне отслеживать давление, изначально, в софте значение давления это переменная флоат, число с хвостом, например 2.5 бар, преобразую например в интежер, получаеться 2 бар.
Как сделать чтобы данные в скаде отображались правильно так же 2.5. бар а не 2 бар

10.03.2022, 15:17 #2

  • Просмотр профиля
  • Сообщения форума
  • Личное сообщение
  • Домашняя страница
  • Просмотр статей

Сергей0308 на форуме

Пользователь Регистрация 25.06.2011 Адрес Галактика Андромеды (M31) Сообщений 8,110

По умолчанию

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

Привет всем, есть вопрос в плане передачи переменной int с пр200 на пк через преобразователь где установлена будет скада, пока не знаю что за версия.
например нужно мне отслеживать давление, изначально, в софте значение давления это переменная флоат, число с хвостом, например 2.5 бар, преобразую например в интежер, получаеться 2 бар.
Как сделать чтобы данные в скаде отображались правильно так же 2.5. бар а не 2 бар

Такое впечатление, что Вы «первый раз замужем»(БМП), короче, округлите до десятых долей, умножьте на 10 и преобразуйте в инт, в ПР всё!
В скаде(или ОРС-сервере) преобразуете обратно во флоат и разделите на 10(перенести запятую на один знак влево), всё!

Последний раз редактировалось Сергей0308; 10.03.2022 в 15:26 .

Если проблему можно решить за деньги, это не проблема, это расходы. Бог каждому посылает проблемы по его силам. Так что одно из двух. Либо ты можешь-таки
справиться с проблемами, либо это не твои проблемы.

Как представить float в виде integer без потери информации?

Есть задача преобразования float значений в значения типа int (одно float значение в одно int значение) без потери информации, т.е., чтобы потом можно было выполнить обратное преобразование. Как это можно реализовать?

Важно

Надо, чтобы при таком преобразовании сохранялся порядок и сумма,
т.е. для любых a, b: float должно выполняться:

to_float(to_int(a) + to_int(b)) == a + b to_int(a) < to_int(b) при a < b и т.д. 

Нашёл на англоязычном SO ответ, где побитово представляется структура float значений, но не представляю, как её можно применить для своей задачи. Примечание: NaN и inf в моей задаче преобразовывать не надо.

Попытки решения

Изначально на ум пришла сериализация с помощью pickle.dumps , а затем получение int из этих байт, но это совсем не рациональное решение и оно совершенно не удовлетворяет требованиям. Были попытки реализовать это через байтовые представления чисел (ответ Qwertiy♦), в таком варианте не сохраняется сумма.

Отслеживать
Mikhail Murugov
задан 19 окт 2020 в 11:41
Mikhail Murugov Mikhail Murugov
5,426 1 1 золотой знак 16 16 серебряных знаков 37 37 бронзовых знаков

Можно использовать Fraction: fractions.Fraction(0.1+0.2) => Fraction(1351079888211149, 4503599627370496) `

26 окт 2020 в 15:38
@vp_arth Да я ему предлагал. Говорит два инта не хочу, хочу один! ))
26 окт 2020 в 15:38

@vp_arth Ок. Можно. А как потом эти числитель и знаменатель хранить в одном int значении? И как их потом друг от друга отделять после сложения, например?

26 окт 2020 в 15:43

Тогда так: ((0.1+0.2)*1e32).as_integer_ratio()[0] / 1e32 == (0.1+0.2) 32 взял «от балды», не в курсе, сколько там точности)

26 окт 2020 в 15:43

@vp_arth В питоне числа с плавающей точкой являются double (64 бит), вроде как. Идею Вашу понял, сейчас попробую потестировать.

26 окт 2020 в 15:51

6 ответов 6

Сортировка: Сброс на вариант по умолчанию

to_float(to_int(a) + to_int(b)) == a + b to_int(a) < to_int(b) при a < b и т.д. 

Я вспомнил, что в питоне int'ы бесконечные. У double есть 11 бит на степень, значит при умножении на 2**(2**12) получится целое число, которое можно положить в int. Только умножать надо по мере перевода, а не дробное число - иначе произойдёт переполнение.

Отслеживать
ответ дан 19 окт 2020 в 16:44
123k 24 24 золотых знака 128 128 серебряных знаков 307 307 бронзовых знаков
Что значит "по мере перевода"? Не могли бы Вы, пожалуйста, приложить пример?
20 окт 2020 в 5:01
@МихаилМуругов, должно быть какое-то сходство с этим: ru.stackoverflow.com/a/734615/178988.
20 окт 2020 в 8:30

Самое простое — просто умножать и делить на достаточно большой коэффициент, чтобы покрыть необходимый диапазон значений.

ratio = (1  
# На некоторых ratio мы таки будем получать получать ровно 0.3 при сложении, так что тут поведение нестабильно assert to_float(to_int(0.1) + to_int(0.2)) == 0.1 + 0.2 assert to_float(to_int(-1.03e-30) + to_int(-2.04e-31)) == (-1.234e-30) assert to_float(to_int(-1.03e+130) + to_int(-2.04e+129)) == (-1.234e+130) assert to_int(1e-300) == 0 try: print(to_int(1e+300)) except OverflowError as e: assert str(e) == 'cannot convert float infinity to integer' # to_int_2 assert to_float(to_int_2(0.1) + to_int_2(0.2)) == 0.1 + 0.2 assert to_float(to_int_2(-1.03e-30) + to_int_2(-2.04e-31)) == (-1.234e-30) assert to_float(to_int_2(-1.03e+130) + to_int_2(-2.04e+129)) == (-1.234e+130) try: to_int_2(1e-300) == 0 except AssertionError as e: assert str(e) == 'Not enough precision' try: print(to_int_2(1e+300)) except OverflowError as e: assert str(e) == 'cannot convert Infinity to integer ratio' 

Сейчас прихожу к выводу, что as_integer_ratio не нужен, достаточно проверки res == 0 and f != 0 в to_int.

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

Преобразование типов данных, это приведение одного типа к другому. Например, приведение целочисленной переменной к числу с плавающей точной, или преобразование числа в строку. В C# выделяют два варианта преобразования типов:

  • Неявное преобразование типов. Это, так называемое безопасное преобразование типов в C#. Например, преобразование из типа float (более «маленький» тип) в тип double (более «большой» тип). При таком преобразовании никакая информация не «потеряется», что при обратном преобразовании вполне возможно.
  • Явное преобразование типов. Такое преобразование выполняется программистом с прямым указанием типа, к которому нужно привести переменную. Для такого преобразования требуется наличие оператора преобразования.

А теперь, я покажу как можно использовать явное преобразование типов в C#:

using System; namespace TypesConvertion < class Program < static void Main(string[] args) < //Число с плавающей точкой double doubleData = 245.45; //Вывод этого числа Console.WriteLine(doubleData); //А теперь, мы сделаем на основе этого числа, цело число int intData = (int)doubleData; //Вывод целого числа Console.WriteLine(intData); //Чтобы окно не закрылось раньше времени Console.ReadKey(); >> >

Преобразование типа double в тип int выполнялось в выделенной строке (строке с номером 16). Если вы соберете данный пример и запустите его, то увидите, что преобразование типов прошло, т.е. из числа с плавающей точкой мы получили целое число.

Так же, для преобразования данных из одного типа в другой, есть целый класс с именем Convert, у которого имеются специальные методы. Ниже, в таблице, представлены основные методы этого класса.

Название метода Целевой тип
ToBoolean bool
ToByte byte
ToChar char
ToDouble double
ToSingle float
ToInt32 int
ToInt64 long
ToString string

А теперь, пример использования класса Convert и его методов:

using System; namespace TypesConvertion < class Program < static void Main(string[] args) < //Число с плавающей точкой double doubleData = 245.45; //Вывод этого числа Console.WriteLine(doubleData); //А теперь, мы сделаем на основе этого числа, цело число int intData = Convert.ToInt32(doubleData); //Вывод целого числа Console.WriteLine(intData); //Чтобы окно не закрылось раньше времени Console.ReadKey(); >> >

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

И обратите внимание на еще одни момент, если один тип нельзя преобразовать в другой, а вы это попытаетесь сделать, то получите ошибку в программе!

Пользоваться возможность преобразования типов вам придется довольно часто!

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

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