When an integer is converted to floating-point, and the value cannot be directly represented by the destination type, the nearest value is usually selected (required by IEEE-754).
I would like to convert an integer to floating-point with rounding towards zero in case the integer value cannot be directly represented by the floating-point type.
Example:
int i = 2147483647; float nearest = static_cast<float>(i); // 2147483648 (likely) float towards_zero = convert(i); // 2147483520
To convert an integer data type to float you can wrap the integer with float64() or float32. Explanation: Firstly we declare a variable x of type int64 with a value of 5. Then we wrap x with float64(), which converts the integer 5 to float value of 5.00. The %.
The floatValue() function can convert a given integer value into float. It belongs to the java. lang. Integer class.
Since C++11, one can use fesetround()
, the floating-point environment rounding direction manager. There are four standard rounding directions and an implementation is permitted to add additional rounding directions.
#include <cfenv> // for fesetround() and FE_* macros #include <iostream> // for cout and endl #include <iomanip> // for setprecision() #pragma STDC FENV_ACCESS ON int main(){ int i = 2147483647; std::cout << std::setprecision(10); std::fesetround(FE_DOWNWARD); std::cout << "round down " << i << " : " << static_cast<float>(i) << std::endl; std::cout << "round down " << -i << " : " << static_cast<float>(-i) << std::endl; std::fesetround(FE_TONEAREST); std::cout << "round to nearest " << i << " : " << static_cast<float>(i) << std::endl; std::cout << "round to nearest " << -i << " : " << static_cast<float>(-i) << std::endl; std::fesetround(FE_TOWARDZERO); std::cout << "round toward zero " << i << " : " << static_cast<float>(i) << std::endl; std::cout << "round toward zero " << -i << " : " << static_cast<float>(-i) << std::endl; std::fesetround(FE_UPWARD); std::cout << "round up " << i << " : " << static_cast<float>(i) << std::endl; std::cout << "round up " << -i << " : " << static_cast<float>(-i) << std::endl; return(0); }
Compiled under g++ 7.5.0, the resulting executable outputs
round down 2147483647 : 2147483520 round down -2147483647 : -2147483648 round to nearest 2147483647 : 2147483648 round to nearest -2147483647 : -2147483648 round toward zero 2147483647 : 2147483520 round toward zero -2147483647 : -2147483520 round up 2147483647 : 2147483648 round up -2147483647 : -2147483520
Omitting the #pragma
doesn't seem to change anything under g++.
@chux comments correctly that the standard doesn't explicitly state that fesetround()
affects rounding in static_cast<float>(i)
. For a guarantee that the set rounding direction affects the conversion, use std::nearbyint
and its -f
and -l
variants. See also std::rint
and its many type-specific variants.
I probably should have looked up the format specifier to use a space for positive integers and floats, rather than stuffing it into the preceding string constants.
(I haven't tested the following snippet.) Your convert()
function would be something like
float convert(int i, int direction = FE_TOWARDZERO){ float retVal = 0.; int prevdirection = std::fegetround(); std::fesetround(direction); retVal = static_cast<float>(i); std::fesetround(prevdirection); return(retVal); }
You can use std::nextafter
.
int i = 2147483647; float nearest = static_cast<float>(i); // 2147483648 (likely) float towards_zero = std::nextafter(nearest, 0.f); // 2147483520
But you have to check, if static_cast<float>(i)
is exact, if so, nextafter
would go one step towards 0, which you probably don't want.
Your convert
function might look like this:
float convert(int x){ if(std::abs(long(static_cast<float>(x))) <= std::abs(long(x))) return static_cast<float>(x); return std::nextafter(static_cast<float>(x), 0.f); }
It may be that sizeof(int)==sizeof(long)
or even sizeof(int)==sizeof(long long)
in this case long(...)
may behave undefined, when the static_cast<float>(x)
exceeds the possible values. Depending on the compiler it might still work in this cases.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With