How to convert a float to an int in modern C++ - c++

As strange as it may seems, I can't find how to cleanly convert a float to an int.
This technique
int int_value = (int)(float_value + 0.5);
triggers a
warning: use of old-style cast
in gcc.
So, what is the modern-style, simple way to convert a float to an int ? (I accept the loss of precision of course)

As Josh pointed out in the comments, + 0.5 is not very reliable. For extra security you could combine a static_cast with std::round like so:
int int_value = static_cast<int>(std::round(float_value));
For the casting part, see this excellent post for an explanation.

try:
int int_value = static_cast<int>(float_value + 0.5);
FYI: different casts in C++ gave a very good explanation about those 4 casts introduced in C++.

You could also consider
int int_value = boost::lexical_cast<int>(float_value);
lexical_cast has the benefit of working for all primitive types, and stl strings etc. It also means you don't have to do the (float_value + 0.5) stuff.

Related

how to remove float leftovers in C++

I would like to remove float leftovers while retaining its type.
(i.e 3.14159f should become 3.0f)
What I can do so far is casting the type twice.
float f = 3.14159f;
float r = static_cast<float>(static_cast<int>(f));
Is this the correct way to do it? or is there any simpler way?
Thank you in advance.
The operation of "removing leftovers" is called truncation. C++ provides std::trunc function to do it (include <cmath> header):
float r = std::trunc(f);
Is this the correct way to do it?
No.
or is there any simpler way?
One single cast should be sufficient:
float r = static_cast<int>(f);
Also as #Baum mit Augen said in their comment:
"This fails for values that don't fit in an int"
So using std::trunc() solves that problem with correct error handling.
That is a correct way to do that, but you can also use floor:
std::cout << std::floor(3.14f); // prints 3

Correctly converting floating point in C++

What would be the correct/recommended way of telling the C++ compiler "only warn me of floating point conversions that I'm not aware of"?
In C, I would enable the warnings related to floating point conversions, and then I would use explicit C-style casts to silence warnings related to the conversions that are under control.
For example, computing a*a*a - b*b is quite prone to overflow in single precision floating point, so you might wish to compute it in double precision and only go single precision later:
double a = 443620.52;
double b = 874003.01;
float c = (float)(a*a*a - b*b);
The above C-style explicit cast would silence the compiler warning about the conversion from double to float.
Reading C++ documentation about casts, I get to the conclusion that the correct way of doing this in C++ would be as follows:
double a = 443620.52;
double b = 874003.01;
float c = static_cast<float>(a*a*a - b*b);
But, is this really the correct way of doing this in C++?
I understand the rationale behind the static_cast syntax being ugly on purpose, so that you avoid casts completely if possible.
Yes, I can omit the explicit cast to float. But then I need to disable compiler warnings telling me of precision loss (or otherwise I'd get a number of irrelevant warnings that would make it difficult to notice really relevant warnings). And if I disable fp-related compiler warnings, I'd lose the possibility of being warned when I'm mistakenly losing precision in other code places.
So, what's the correct approach for floating point conversions in C++?
Yes
float c = static_cast<float>(a*a*a - b*b);
is the correct way of explicitly casting to float in C++. You can also do:
float c = (float)(a*a*a - b*b);
but using a "C-style" cast like that is bad style because static_cast will hide rather fewer errors than C-style.
Alternatively, if you are doing this a lot, you can define a function:
inline float flt(double d){return static_cast<float>(d);}
and then you can write:
float c = flt(a*a*a - b*b);
which is even more compact than the original C (and will be optimized away to nothing).
As far as I am aware, there are three different ways to avoid the warning:
C-style cast
static_cast
Constructor-style cast (e.g. float c = float(a*a*a-b*b))
In the code example below, c1, c2 and c3 avoid the warnings:
int main()
{
double a = 443620.52;
double b = 874003.01;
// These three versions avoid the conversion warnings:
float c1 = (float)(a*a*a - b*b);
float c2 = static_cast<float>(a*a*a - b*b);
float c3 = float(a*a*a - b*b);
// Only these two give conversion warnings:
float c4(a*a*a - b*b);
float c5 = a*a*a - b*b;
(void)c1; // Just to avoid unused-variable warnings
(void)c2;
(void)c3;
(void)c4;
(void)c5;
}
Only c4 and c5 trigger a warning. Check the live demo to see the results.

Should I always use the appropriate literals for number types?

I'm often using the wrong literals in expressions, e.g. dividing a float by an int, like this:
float f = read_f();
float g = f / 2;
I believe that the compiler will in this case first convert the int literal (2) to float, and then apply the division operator. GCC and Clang have always let stuff like that pass, but Visual C++ warns about an implicit conversion. So I have to write it like this:
float f = read_f();
float g = f / 2.0f;
That got me wondering: Should I always use the appropriate literals for float, double, long etc.? I normally use int literals whenever I can get away with it, but I'm not sure if that's actually a good idea.
Is this a likely cause of subtle errors?
Is this only an issue for expressions or also for function parameters?
Are there warning levels for GCC or Clang that warn about such implicit conversions?
How about unsigned int, long int etc?
You should always explicitly indicate the type of literal that you intend to use. This will prevent problems when for example this sort of code:
float foo = 9.0f;
float bar = foo / 2;
changes to the following, truncating the result:
int foo = 9;
float bar = foo / 2;
It's a concern with function parameters as well when you have overloading and templates involved.
I know gcc has -Wconversion but I can't recall everything that it covers.
For integer values that fit in int I usually don't qualify those for long or unsigned as there is usually much less chance there for subtle bugs.
There's pretty much never an absolutely correct answer to a "should" question. Who's going to use this code, and for what? That's relevant here. But also, particularly for anything to do with floats, it's good to get into the habit of specifying exactly the operations you require. float*float is done in single-precision. anything with a double is done double-precision, 2 gets converted to a double so you're specifying different operations here.
The best answer here is What Every Computer Scientist Should Know About Floating-Point Arithmetic. I'd say don't tl;dr it, there are no simple answers with floating point.

Int or Unsigned Int to float without getting a warning

Sometimes I have to convert from an unsigned integer value to a float. For example, my graphics engine takes in a SetScale(float x, float y, float z) with floats and I have an object that has a certain size as an unsigned int. I want to convert the unsigned int to a float to properly scale an entity (the example is very specific but I hope you get the point).
Now, what I usually do is:
unsigned int size = 5;
float scale = float(size);
My3DObject->SetScale(scale , scale , scale);
Is this good practice at all, under certain assumptions (see Notes)? Is there a better way than to litter the code with float()?
Notes: I cannot touch the graphics API. I have to use the SetScale() function which takes in floats. Moreover, I also cannot touch the size, it has to be an unsigned int. I am sure there are plenty of other examples with the same 'problem'. The above can be applied to any conversion that needs to be done and you as a programmer have little choice in the matter.
My preference would be to use static_cast:
float scale = static_cast<float>(size);
but what you are doing is functionally equivalent and fine.
There is an implicit conversion from unsigned int to float, so the cast is strictly unnecessary.
If your compiler issues a warning, then there isn't really anything wrong with using a cast to silence the warning. Just be aware that if size is very large it may not be representable exactly by a float.

Casting an array of unsigned chars to an array of floats

What is the best way of converting a unsigned char array to a float array in c++?
I presently have a for loop as follows
for (i=0 ;i< len; i++)
float_buff[i]= (float) char_buff[i];
I also need to reverse the procedure, i.e convert from unsigned char to float (float to 8bit conversion)
for (i=0 ;i< len; i++)
char_buff[i]= (unsigned char) float_buff[i];
Any advice would be appreciated
Thanks
I think the best way is to use a function object:
template <typename T> // T models Any
struct static_cast_func
{
template <typename T1> // T1 models type statically convertible to T
T operator()(const T1& x) const { return static_cast<T>(x); }
};
followed by:
std::transform(char_buff, char_buff + len, float_buff, static_cast_func<float>());
std::transform(float_buff, float_buff + len, char_buff, static_cast_func<unsigned char>());
This is the most readable because it says what is being done in English: transforming a sequence into a different type using static casting. And future casts can be done in one line.
Your solution is pretty much the best option, however, I would consider switching to:
char_buff[i]= static_cast<unsigned char>(float_buff[i]);
The cast is automatic so you don't need to make it explicit.
But you can use the standard algorithms:
std::copy(char_buff,char_buff+len,float_buff);
Converting back from float to char there is a potential loss of information. So you need to be more explicit.
std::transform(float_buff,float_buff+len,char_buff,MyTransform());
Here we use the class MyTransform which should have an operator() that takes a float and returns a char. That should be trivial to impliment.
Your solution seems right, though on the way back, you might lose the floating digits in the casting.
For what purpose are you doing this? Shoving a float into a char doesn't really make sense. On most platforms a float will be 4 bytes and represent a floating point number, where as a char will be 1 byte and often represents a single character. You'll lose 3 bytes of data trying to shove a float into a char, right?
Your first loop doesn't require a cast. You can implicitly convert from one type (e.g., unsigned char) to a wider type (e.g., float). Your second loop should use static_cast:
for (i=0; i< len; i++)
char_buff[i]= static_cast<unsigned char>(float_buff[i]);
We use static_cast to explicitly tell the compiler to do the conversion to a narrower type. If you don't use the cast, your compiler might warn you that the conversion could lose data. The presence of the cast operator means that you understand you might lose data precision and you're ok with it. This is not an appropriate place to use reinterpret_cast. With static_cast, you at least have some restrictions on what conversions you can do (e.g., it probably won't let you convert a Bird* to a Nuclear_Submarine*). reinterpret_cast has no such restrictions.
Also, here's what Bjarne Stroustrup has to say about this subject.
If you are dealing with very large arrays and performance is essential then the following may prove slightly more efficient:
float *dst = float_buff;
unsigned char *src = char_buff;
for (i=0; i<len; i++) *dst++ = (float)*src++;
No one has mentioned this, but if you're doing any arithmetic with the floats, you may want to round instead of truncate... if you have the char 49, and it gets turned into 4.9E1, after some arithmetic, it might turn into 4.89999999E1 which will turn into 48 when you turn it back into a char.
If you're not doing anything with the float, this shouldn't be a problem, but then why do you need it as a float in the first place?