Поведение может зависеть от действующих опций компилятора.Например, в msvc /fp:fast
жертвует правильностью ради скорости.Если это не то, что вы хотите, укажите /fp:strict
или /fp:precise
(по умолчанию).На Clang -menable-unsafe-fp-math
делает что-то похожее.
Режим округления с плавающей запятой управляется fesetround
.
Получитьрежим округления, используя fegetround
, чтобы вы могли восстановить его позже, затем используйте fesetround
, чтобы установить нужный режим округления (в вашем случае FE_TOWARDZERO
, если вы имеете в виду наименьшую по величине, или FE_DOWNWARD
в противном случае), затем приведите его кfloat
.Наконец, восстановите режим округления.
inline float cast_with_mode(int32_t value, int mode){
int prevmode = fegetround();
if(prevmode == mode) return (float)value; // may be faster without this
fesetround(mode);
float result = (float)value;
fesetround(prevmode);
return result;
}
По производительности, лучше или не лучше сравнивать prevmode
с mode
.Если это уже правильно, вам не нужно ни устанавливать его, ни восстанавливать.Является ли сравнение быстрее или медленнее, чем установка / восстановление, я не знаю.
Пример вывода (то же самое на Clang и G ++):
Mode Value Value ResultBits Result Value
FE_TOWARDZERO: 2147483520 0x7fffff80 => 4effffff 2147483520.000000
FE_UPWARD: 2147483520 0x7fffff80 => 4effffff 2147483520.000000
FE_TOWARDZERO: 2147483584 0x7fffffc0 => 4effffff 2147483520.000000
FE_UPWARD: 2147483584 0x7fffffc0 => 4f000000 2147483648.000000