wizzard: (Default)
[personal profile] wizzard

Long story short: написать функцию целочисленного деления, с округлением “вверх” (к ближайшему целому, которое больше или равно результату, полученному в результате деления вещественных (float) чисел). Без использования floating-point arithmetic и 64bit arithmetic. Для signed int32.

Если честно – я подумал и решил забить. Кому надо реализовать корректно – интернет знает решение. А кому хочется поломать мозги – милости просим в комменты :)

UPD: хехе, now i have a solution. но подсмотренный вариант Майка Абраша все равно лучше – он гораздо читабельнее.

From: (Anonymous)
Вариант С'89:

signed int div_up(signed int lhs, signed int rhs)
{
signed int mod
, flag
, sign
, div_low;

div_low = lhs / rhs;
sign = div_low / -div_low;
mod = lhs % rhs;
flag = abs(rhs / mod);

return ( flag < 2 || flag == 2 && (rhs % mod) == 0 ) ? div_low + (1 * sign)
: div_low;
}


Вариант С++'03 для любого типа, отвечающего концепту целого числа:

template
<
typename IntType
>
IntType div_up(const IntType lhs, const IntType rhs)
{
BOOST_CONCEPT_ASSERT((Integer));

IntType div_low = lhs / rhs
, sign = div_low / -div_low
, mod = lhs % rhs
, flag = std::abs(rhs / mod);

return ( flag < 2 || flag == 2 && (rhs % mod) == 0 ) ? div_low + (1 * sign)
: div_low;
}

Я, как в том анегдоте, **ал и плакал. Мельчает народ наш, если уж такие задачки называют "убийственными".
From: (Anonymous)
Забыл добавить, эта функция округляет вверх не всегда, а по правилам "жизненной" арифметики, то есть с дробной частью от .5 и выше. Если округлять всегда, то это вообще в одну строку всё пишется.

Profile

wizzard: (Default)
wizzard

January 2019

S M T W T F S
  12 345
6789101112
1314 1516171819
202122 23242526
2728293031  

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jan. 24th, 2026 06:50 pm
Powered by Dreamwidth Studios