Округление 64-битных целых до 32-битных целых - PullRequest
0 голосов
/ 20 февраля 2020

У меня есть функция, которая выполняет операцию округления, как показано ниже. Он принимает 64-битное целое число в качестве входных данных и дает 32-битное целое число в качестве выходных данных. При преобразовании ко входу добавляется коэффициент 0x40000000. В чем причина этого?

int rounder(long long int in)
{
  INT64 out;
  if ((in >> 32) == 0x7FFFFFFF)
    out = in;
  else
    out = (INT64)0x40000000 + in; 
  out = out >> 31; 
  return (INT32)out;
}

Ответы [ 2 ]

2 голосов
/ 20 февраля 2020

Давайте начнем с нескольких меньших чисел, потому что они проще!

При обычном округлении x.49999 ... или меньше должно округляться до x, x.50000 ... или больше при округлении до (х + 1).

(Есть лотов различных методов округления, но это самый урок в школе.)

Всякий раз, когда вы делаете целочисленное деление (или преобразование с плавающей запятой) значение в целое число), вы просто отбрасываете дробную часть. Следовательно:

6/2 == 3.0  --> 3
5/2 == 2.5  --> 2

Аккуратный трюк состоит в том, чтобы добавить половину делителя (в данном случае 1) перед делением. Как будто с помощью маги c вы получаете правильное округление! Например:

6/2  becomes  (6+1)/2  == 7/2 == 3.5  --> 3
5/2  becomes  (5+1)/2  == 6/2 == 3.0  --> 3

Вы можете понять, почему это работает, посмотрев на это так:

 5/2  becomes  (5+1)/2  ==   5/2 + 1/2
13/6  becomes (13+3)/6  ==  13/6 + 3/6   == 13/6 + 1/2

Вы добавляете половину к реальному ответу. Все, что меньше x.5, все равно будет меньше, чем x + 1, поэтому все равно будет округляться, все x5 или больше станет x + 1 или больше, поэтому округлится.

Теперь к вашему актуальному вопросу : Эта идея работает со всеми делителями; вы смещаетесь вниз на 31, что равняется делению на 2 ^ 31. Таким образом, «половина делителя» равна 2 ^ 30 или 0x40000000.

Осторожно: как уже отмечали другие, этот «трюк» работает только для положительных чисел (вычитать нужно, если он отрицательный, но это банка червей).

В этой теме есть что рассмотреть; это не просто разобраться. Как всегда, попробуйте несколько простых примеров для себя и посмотрите, что произойдет.

0 голосов
/ 20 февраля 2020

Входными данными являются 64-битные числа с фиксированной запятой и 31-битным дробным числом. Значение 0x40000000 добавляется для округления числа вверх, если оно имеет дробную часть> = 0,5. if используется, чтобы избежать возможного переполнения при учете округления.

...