Умножение отрицательных чисел с фиксированной точкой


У меня есть следующий метод умножения двух 32-битных чисел в фиксированной точке Формат 19.13. Но я думаю, что есть проблема с этим методом:

1.5f округляется до 2.0f, в то время как -1.5f округляется до -1.0f.

Мне кажется, что -1.5 следует округлить до -2.0f.

Во-первых, имеет ли смысл текущее округление, и если нет, то как я могу его изменить быть более последовательным?

static OPJ_INT32 opj_int_fix_mul(OPJ_INT32 a, OPJ_INT32 b) {
    OPJ_INT64 temp = (OPJ_INT64) a * (OPJ_INT64) b ;
   temp += 4096;
   assert((temp >> 13) <= (OPJ_INT64)0x7FFFFFFF);
   assert((temp >> 13) >= (-(OPJ_INT64)0x7FFFFFFF - (OPJ_INT64)1));
   return (OPJ_INT32) (temp >> 13);
}
1 9

1 ответ:

Поскольку вы всегда добавляете 4096, код делает округление на полпути к положительной бесконечности. Это довольно странно.

Чтобы округлить к положительной бесконечности, я бы ожидал

temp += 4096 + 4095;

Чтобы округлить обычным образом (до ближайшего), используйте вместо этого добавить смещение от 0.

temp += (temp < 0) ? -4096 : 4096;

Округлить до ближайших исвязей еще больше работы. Не уверен, что ОП этого хочет.