12 ноября 2007

Integer division with rounding

Понадобилось мне целочисленное деление с округлением результата (точнее не целочисленное, а с фиксированной точкой - но суть-то, как известно, одна). "С округлением" - это когда 10/3=3, а 20/3=7.

С математикой у меня туго, поэтому написал это дело так:
__int64 RoundedDivision(__int64 Dividend, __int64 Divisor)
{
__int64 DoubleResult = (Dividend << 1) / Divisor;
return ((DoubleResult < 0) ? DoubleResult : (DoubleResult + 1)) >> 1;
}
Однако не покидает мысль что можно написать как-то попроще.

PS. Заодно немного потормозил над тем, что при отрицательном знаке DoubleResult не нужно вычитать единичку. Видимо совсем забыл как считать в дополнительном коде.

2 комментария:

CTpaHHoe комментирует...

floor(Dividend/Divisor + 0.5) подойдёт?

Raider комментирует...

Наверно ты имеешь ввиду floor((long double)Dividend/Divisor + 0.5)

__int64 в double не влезет, придется использовать long double. Чё-то мне кажется что вся эта хрень будет жутко тормозить по сравнению с приведенной мною целочисленной конструкцией: ведь понадобится перевод в плавающую точку, потом деление и сложение long double, вызов floor(), потом перегон обратно из сопроцессора... Мерять производительность лень, но ставлю что вся эта затея с сопроцессором проиграет по скорости моему варианту.