72

What are the different techniques used to convert float type of data to integer in 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; } 
1

11 Answers 11

113

What you are looking for is 'type casting'. typecasting (putting the type you know you want in brackets) tells the compiler you know what you are doing and are cool with it. The old way that is inherited from C is as follows.

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

If you had only tried to write

int var_b = var_a; 

You would have got a warning that you can't implicitly (automatically) convert a float to an int, as you lose the decimal.

This is referred to as the old way as C++ offers a superior alternative, 'static cast'; this provides a much safer way of converting from one type to another. The equivalent method would be (and the way you should do it)

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

This method may look a bit more long winded, but it provides much better handling for situations such as accidentally requesting a 'static cast' on a type that cannot be converted. For more information on the why you should be using static cast, see this question.

Sign up to request clarification or add additional context in comments.

7 Comments

I didn't downvote, but it may be due to you using C style casts in C++ code. It's frowned upon as it's bad style
I am? really? sorry, that was the way I though I was meant to do them
"Proper" way is static cast. Pragmatic way is this. I'm going for pragmatic. =)
wow, talk about digging up the paste. I think we can all agree that accepting the technically, TECHNICALLY, C casts are still valid C++ and should be covered... boy have I learnt a lot since I first wrote this answer :P
Aside from maybe NaN, how could the above "old way" code result in an unconvertible type? We know in advance that var_a is a float.
|
45

Normal way is to:

float pi = 3.1415; int i = static_cast<int>(f); // i = 3 

Always rounds down:

float f = 3.999; int n = static_cast<int>(f); // n = 3 

2 Comments

Additional information on the result would be helpful.
static_cast<> is preferred to dynamic cast which would be : int n = (int)f; because static cast is resolved during compilation so the dev will catch the error (if any) during compilation. whereas dynamic cast is a runtime conversion so the developer can catch the error only if it happens during runtime.
18

Size of some float types may exceed the size of int. This example shows a safe conversion of any float type to int using the int safeFloatToInt(const FloatType &num); function:

#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; } 

Result:

Unsafe conversion of value:2.2518e+15 2147483647 43 23333 

4 Comments

@dgrat I just pasted the whole thing into an online compiler (C++14) and it compiled and run fine.
Isn't there a slight numeric_limits<int>::max() could get rounded to a slightly larger float value, and then if you pass exactly this larger value to safeFloatToInt it will pass the checks (because it uses strict inequalities) but still be undefined?
"This example shows a safe conversion..." As suggested by Arthur Tacca, this is simply not true. For example, on x86-64 clang 12.0.1, calling safeFloatToInt(b) with float b = std::numeric_limits<int>::max() - x; will cause UB for 0 < x < 64.
After having taken a closer took, the observed UB doesn't seem to be caused by what Arthur is suggesting. While my previous comment still holds true, the check that compares the number of digits of each type is producing false results and likely has its logic reversed.
10

For most cases (long for floats, long long for double and long double):

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

Comments

3

Check out the boost NumericConversion library. It will allow to explicitly control how you want to deal with issues like overflow handling and truncation.

Comments

1

I believe you can do this using a cast:

float f_val = 3.6f; int i_val = (int) f_val; 

Comments

1

the easiest technique is to just assign float to int, for example:

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

this will truncate everything behind floating point or you can round your float number before.

Comments

1

One thing I want to add. Sometimes, there can be precision loss. You may want to add some epsilon value first before converting. Not sure why that works... but it work.

int someint = (somedouble+epsilon); 

1 Comment

It works because the cast to integer truncates instead of rounding. There might be cases where you want your float to be 5 for instance but the computer stores it as 4.999..., so if you cast to int without the epsilon it will unintentionally become 4.
0

I know this is an old question, but hope my answer can help. Here what I use in for my microcontroller:

 float temperature = 31.14 float humidity = 66.70 int intTemperature = static_cast<int>(round(temperature)); int intHumidity = static_cast<int>(round(humidity)); 

1 Comment

It would be great if you could edit your answer to add more details as to what 'round' does. Despite the name there are several rounding modes - what is the default? Maybe add a link e.g. to cppreference.
-1

This is one way to convert IEEE 754 float to 32-bit integer if you can't use floating point operations. It has also a scaler functionality to include more digits to the result. Useful values for scaler are 1, 10 and 100.

#define EXPONENT_LENGTH 8 #define MANTISSA_LENGTH 23 // to convert float to int without floating point operations int ownFloatToInt(int floatBits, int scaler) { int sign = (floatBits >> (EXPONENT_LENGTH + MANTISSA_LENGTH)) & 1; int exponent = (floatBits >> MANTISSA_LENGTH) & ((1 << EXPONENT_LENGTH) - 1); int mantissa = (floatBits & ((1 << MANTISSA_LENGTH) - 1)) | (1 << MANTISSA_LENGTH); int result = mantissa * scaler; // possible overflow exponent -= ((1 << (EXPONENT_LENGTH - 1)) - 1); // exponent bias exponent -= MANTISSA_LENGTH; // modify exponent for shifting the mantissa if (exponent <= -(int)sizeof(result) * 8) { return 0; // underflow } if (exponent > 0) { result <<= exponent; // possible overflow } else { result >>= -exponent; } if (sign) result = -result; // handle sign return result; } 

Comments

-1

When you'd like to round the result as well you can e.g.

std::cout << static_cast<int>(2.49f+0.5f);//2 std::cout << static_cast<int>(2.51f+0.5f);//3 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.