У меня есть некоторые места в моем коде, где я хочу убедиться, что деление на 2 произвольных числа с плавающей запятой (32-битная одинарная точность) не переполнится. Цель/компилятор не гарантирует (достаточно явно) хорошую обработку -INF/INF и (не полностью гарантирует IEEE 754 для исключительных значений - (возможно, неопределенный) - и цель может измениться). Кроме того, я не могу делать предположения о входных данных для этих нескольких специальных мест, и я привязан к стандартным библиотекам C90.
Я прочитал Что каждый программист должен знать об арифметике с плавающей запятой но, честно говоря, я немного растерялся.
Итак... Я хочу спросить сообщество, поможет ли следующий фрагмент кода, и есть ли способы сделать это лучше/быстрее/точнее/правильнее:
#define SIGN_F(val) ((val >= 0.0f)? 1.0f : -1.0f)
float32_t safedivf(float32_t num, float32_t denum)
{
const float32_t abs_denum = fabs(denum);
if((abs_denum < 1.0f) && ((abs_denum * FLT_MAX) <= (float32_t)fabs(num))
return SIGN_F(denum) * SIGN_F(num) * FLT_MAX;
else
return num / denum;
}
Изменить: изменено ((abs_denum * FLT_MAX) < (float32_t)fabs(num))
на ((abs_denum * FLT_MAX) <= (float32_t)fabs(num))
по рекомендации Паскаля Куока.
SIGN_F(val)
неправильно извлекает знак-0.0
, поэтому1.0 / -0.0
в конечном итоге будет+FLT_MAX
. Вы можете или не можете возражать. Если вы не уверены в IEEE 754, возможно, вы не можете быть уверены и вcopysign
, но если он есть, вы можете его использовать. - person Pascal Cuoq   schedule 14.08.2014==
,>
и т. д. знаковые нули неразличимы. Вы должны 1- использоватьcopysign
, или 2- обращаться к представлению черезunion
, или 3- делить на него и вызывать то самое переполнение, которого вы пытаетесь избежать. Это оставляет вам решение 2-. - person Pascal Cuoq   schedule 14.08.2014atan2f(y,x)
различает+0.0
и-0.0
сatan2f(zero, -1.0)
, который возвращает+pi
или-pi
в зависимости от+0
,-0
. - person chux - Reinstate Monica   schedule 14.08.2014SIGN_F
вы можете использоватьsignbit
илиcopysign
Есть ли стандартная функция знака (signum, sgn) в C/C++? - person phuclv   schedule 09.04.2019