Преобразование с плавающей запятой С++ в целочисленный тип

Какие различные методы используются для преобразования данных типа float в целое число в C++?

#include <iostream>

using namespace std;
struct database {
  int id, age;
  float salary;
};

int main() {
  struct database employee;
  employee.id = 1;
  employee.age = 23;
  employee.salary = 45678.90;
  /*
     How can i print this value as an integer
     (with out changing the salary data type in the declaration part) ?
   */
  cout << endl << employee.id << endl << employee.
  age << endl << employee.salary << endl;
  return 0;
}

person Community    schedule 30.03.2010    source источник
comment
cs.tut.fi/~jkorpela/round.html   -  person Bertrand Marron    schedule 30.03.2010


Ответы (8)


То, что вы ищете, это «приведение типов». приведение типов (в квадратных скобках известный тип, который вам нужен) сообщает компилятору, что вы знаете, что делаете, и не против. Старый способ, унаследованный от C, выглядит следующим образом.

float var_a = 9.99;
int   var_b = (int)var_a;

Если бы вы только попытались написать

int var_b = var_a;

Вы бы получили предупреждение о том, что вы не можете неявно (автоматически) преобразовать float в int, поскольку вы теряете десятичную дробь.

Это называется старым способом, поскольку C++ предлагает превосходную альтернативу, «статическое приведение»; это обеспечивает гораздо более безопасный способ преобразования одного типа в другой. Эквивалентным методом будет (и способ, которым вы должны это сделать)

float var_x = 9.99;
int   var_y = static_cast<int>(var_x);

Этот метод может показаться немного более длинным, но он обеспечивает гораздо лучшую обработку таких ситуаций, как случайный запрос «статического приведения» к типу, который не может быть преобразован. Для получения дополнительной информации о том, почему вы должны использовать статическое приведение, см. этот вопрос.

person Community    schedule 30.03.2010
comment
Я не понизил голос, но это может быть связано с тем, что вы используете приведение стилей C в коде C++. Это не одобряется, так как это плохой стиль - person Glen; 30.03.2010
comment
Я? В самом деле? извините, это было так, как я, хотя я должен был сделать их - person thecoshman; 30.03.2010
comment
Правильный способ - статический бросок. Прагматичный путь таков. Я выбираю прагматик. знак равно - person cib; 06.05.2013
comment
вау, поговорим о выкапывании пасты. Я думаю, мы все можем согласиться с тем, что принятие технически, ТЕХНИЧЕСКИ приведения C по-прежнему действует C ++ и должно быть покрыто ... мальчик, я многому научился с тех пор, как впервые написал этот ответ: P - person thecoshman; 07.05.2013
comment
Помимо, может быть, NaN, как приведенный выше старый код мог привести к непреобразуемому типу? Мы заранее знаем, что var_a — это число с плавающей запятой. - person Aaron Franke; 02.11.2018
comment
@AaronFranke, что ты имеешь в виду? Если у вас есть число с плавающей запятой, вы можете «стиль C» преобразовать его в int, но использовать такой подход — плохая практика, см. связанный вопрос. - person thecoshman; 02.11.2018

Обычный способ:

float f = 3.4;
int n = static_cast<int>(f);
person Community    schedule 30.03.2010
comment
Дополнительная информация о результате была бы полезной. - person ManuelSchneid3r; 30.10.2016
comment
static_cast‹› предпочтительнее динамического приведения, которое будет: int n = (int)f; потому что статическое приведение разрешается во время компиляции, поэтому разработчик поймает ошибку (если она есть) во время компиляции. тогда как динамическое приведение — это преобразование во время выполнения, поэтому разработчик может поймать ошибку, только если она произойдет во время выполнения. - person george; 21.09.2020

Размер некоторых типов float может превышать размер int. В этом примере показано безопасное преобразование любого типа с плавающей запятой в int с помощью функции int safeFloatToInt(const FloatType &num);:

#include <iostream>
#include <limits>
using namespace std;

template <class FloatType>
int safeFloatToInt(const FloatType &num) {
   //check if float fits into integer
   if ( numeric_limits<int>::digits < numeric_limits<FloatType>::digits) {
      // check if float is smaller than max int
      if( (num < static_cast<FloatType>( numeric_limits<int>::max())) &&
          (num > static_cast<FloatType>( numeric_limits<int>::min())) ) {
         return static_cast<int>(num); //safe to cast
      } else {
        cerr << "Unsafe conversion of value:" << num << endl;
        //NaN is not defined for int return the largest int value
        return numeric_limits<int>::max();
      }
   } else {
      //It is safe to cast
      return static_cast<int>(num);
   }
}
int main(){
   double a=2251799813685240.0;
   float b=43.0;
   double c=23333.0;
   //unsafe cast
   cout << safeFloatToInt(a) << endl;
   cout << safeFloatToInt(b) << endl;
   cout << safeFloatToInt(c) << endl;
   return 0;
}

Результат:

Unsafe conversion of value:2.2518e+15
2147483647
43
23333
person Community    schedule 30.03.2010
comment
@dgrat Я только что вставил все это в онлайн-компилятор (С++ 14), и он скомпилировался и заработал нормально. - person Arthur Tacca; 17.10.2019
comment
Разве небольшое numeric_limits<int>::max() не может быть округлено до немного большего значения с плавающей запятой, а затем, если вы передадите именно это большее значение safeFloatToInt, оно пройдет проверки (поскольку оно использует строгое неравенство), но все равно будет неопределенным? - person Arthur Tacca; 17.10.2019

В большинстве случаев (long для поплавков, long long для double и long double):

long a{ std::lround(1.5f) }; //2l
long long b{ std::llround(std::floor(1.5)) }; //1ll
person Community    schedule 27.04.2016

Ознакомьтесь с повышением NumericConversion библиотека. Это позволит явно контролировать, как вы хотите решать такие проблемы, как обработка переполнения и усечение.

person Community    schedule 30.03.2010

Я считаю, что вы можете сделать это с помощью приведения:

float f_val = 3.6f;
int i_val = (int) f_val;
person Community    schedule 30.03.2010

самый простой способ - просто присвоить значение float для int, например:

int i;
float f;
f = 34.0098;
i = f;

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

person Community    schedule 30.03.2010

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

int someint = (somedouble+epsilon);
person Community    schedule 20.08.2015
comment
Это работает, потому что приведение к целому числу усекается, а не округляется. Могут быть случаи, когда вы хотите, чтобы ваше число с плавающей запятой было, например, 5, но компьютер сохраняет его как 4.999..., поэтому, если вы приведете к типу int без эпсилон, оно непреднамеренно станет 4. - person 16807; 01.03.2021