infoclogged
infoclogged

Reputation: 4017

Efficient way to drop the fractional part from float but retain the type

I know that by std::round, std::floor or std::ceil or simply typecasting we can drop the decimal part, but with typecasting, the the variable loses its original type ( float or double ).

Is there any way, I can retain the type and still drop the fractional part efficiently.

One of the method I thought was subtracting the fractional part from the number, but that isnt so efficient. So, maybe there are some other methods?

Example -

float a = 123.456;

float b;

b = do something on a;

result b is 123.0

Upvotes: 0

Views: 1562

Answers (2)

Evg
Evg

Reputation: 26362

For example, with std::round original type is preserved:

float round(float arg);
double round(double arg);

It is also true for std::floor and std::ceil.

Addition. Here are some benchmarking results.

Compiler     raw loop   std::ceil  std:floor  std::trunc  std::round
--------------------------------------------------------------------
gcc          8.36       8.20       8.19       8.21        32.95
gcc(f)       2.88       8.20       8.20       8.20        11.01
msvs         8.20       28.47      31.90      67.14       97.84
msvs(f)      8.13       13.70      14.00      67.27       97.50

Compilers: gcc 7.3.0 and msvs 2018 15.9.0, machine: Core i7-4770.

Code. Compilation options:

gcc: --std=c++17 -O3 -m64 -march=native -fno-tree-vectorize
gcc(f): --std=c++17 -O3 -m64 -march=native -ffast-math -fno-tree-vectorize
msvs: /fp:precise /fp:except /O2 /std:c++latest ...
msvs(f): /fp:fast /fp:except- /O2 /std:c++latest ...

Frankly speaking I don't think these results are very relevant (in the absolute values) on their own. With fast math option some functions reduce just to a single assembly instruction vroundss. The real code should be profiled to get relevant results.

Upvotes: 7

melpomene
melpomene

Reputation: 85897

Check out modf:

#include <cmath>

float a = 123.456;
float b, c;

c = std::modf(a, &b);
// c = 0.456
// b = 123.0

You don't have to use the return value (the fractional part) if you don't need it.

Or (since C++11) trunc:

float b = std::trunc(a);

Upvotes: 5

Related Questions