Конвертируйте большие int в плавающие без округления c ++ - PullRequest
0 голосов
/ 23 мая 2018

Существует ли быстрый и чистый способ конвертировать int32_t (или больше) в наибольшее представимое значение в float, не превышающее исходное значение, хранящееся в int32_t?

Согласно стандарту IEEE754 (только для чтения в Википедии)https://en.wikipedia.org/wiki/Single-precision_floating-point_format), преобразование больших целых чисел выполняется посредством округления до ближайшего кратного степени 2. Какая степень зависит от величины этого значения.

Однако я хотел бы знать, возможно ли этовместо этого сделать это преобразование в «наибольшее число с плавающей точкой не большего размера» и сделать это чистым способом без сложных конструкций, в идеале путем установки какого-либо флага или с помощью некоторых встроенных инструкций?

РЕДАКТИРОВАТЬ: Iимеют значение x_int, хранящееся в int32_t или int64_t, и я хочу преобразовать его в значение с плавающей запятой x_float, чтобы для этих значений (математически, а не в языке программирования)

x_int> = x_float

всегда верно. Возможный обходной путь для int32_t - использовать double, но я не уверен насчет int64_t.

1 Ответ

0 голосов
/ 23 мая 2018

Поведение может зависеть от действующих опций компилятора.Например, в 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...