How can I convert an integer to float with rounding towards zero?

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

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)