Можно доказать, что следующее корректно:
c = floor((a+b/2)/b)
a = a - c*b
Записывают то средство пола вокруг, к отрицательной бесконечности: не к 0. (Например, пол (-3.1) =-4. Эти floor()
библиотечные функции сделают это; просто обязательно не просто бросьте к интервалу, который будет обычно вокруг к 0 вместо этого.)
, По-видимому b
строго положительно, потому что иначе никакой цикл никогда не будет завершаться: добавление b
не сделает a
больше, и вычитающий b
не сделает a
меньший. С тем предположением мы можем доказать, что вышеупомянутый код работает. (И код paranoidgeek также почти корректен, за исключением того, что он использует бросок для интервала вместо floor
.)
Умный способ доказать его : код добавляет или вычитает кратные числа b
от [1 110], пока a
не находится в [1 112], который можно просмотреть как добавление или вычитание , целые числа от [1 113] до a/b
находятся в [1 115], т.е. до (a/b+1/2)
(звоните, это x
) находится в [1 118]. Поскольку Вы только изменяете его целыми числами, значение [1 119] не изменяется mod 1
, т.е. это переходит к модификация остатка 1 , который является x-floor(x)
. Так эффективное количество вычитаний Вы делаете (который является c
), floor(x)
.
Утомительный способ доказать его :
В конце первого цикла, значение [1 124] является отрицанием количества раз выполнения цикла, т.е.:
, где x = (a+b/2)/b
, таким образом, c: 0, если x> 0 и "потолок (x)-1" иначе. Если первый цикл работал вообще, то это был в‰ ¤-b/2 незадолго до в прошлый раз , цикл выполнялся, таким образом, это - в‰ ¤-b/2+b теперь, т.е. в‰ ¤ b/2. Смотря по тому, как, является ли это точно b/2 или не (т.е. ли x
то, когда Вы запустили, было точно неположительным целым числом или не), второй цикл работает точно в 1 раз или 0, и c или перекрывает (x) или перекрывает (x)-1. Таким образом, это решает его для случая, когда первый цикл действительно работал.
, Если первый цикл не работал, то значение c в конце второго цикла:
, где y = (a-b/2)/b
, таким образом, c: 0, если y< 0 и 1+floor (год) иначе. [И a
теперь, конечно, < b/2 и ≥В-b/2.]
, Таким образом, можно записать выражение для [1 129] как:
x = (a+b/2)/b
y = (a-b/2)/b
c = (x≤0)*(ceiling(x) - 1 + (x is integer))
+(y≥0)*(1 + floor(y))
, Конечно, затем Вы замечаете, что (ceiling(x)-1+(x is integer))
то же как [1 131], который является floor(x)
, и что y
на самом деле x-1
, таким образом (1+floor(y))=floor(x)
, и что касается условных выражений:
, когда xв‰ 0¤, не может случиться так, что (y≥0), таким образом c
просто первый срок, который является floor(x)
,
когда 0 < x < 1, ни одно из условий не содержит, таким образом c
0
,
, когда 1 в‰ ¤В x, тогда только 0в‰ ¤y, таким образом, c является просто вторым сроком, который является floor(x)
снова. Так c = floor(x)
во всех случаях.
Я думаю, что Вы хотите что-то вроде этого:
c = ((int) a + b / 2 * sign(a)) / b
, Который должен соответствовать Вашим циклам за исключением определенных случаев, где b нечетен, потому что диапазон от-b/2 до b/2 меньше, чем b, когда b нечетен.
Принятие b положительно, брюшной пресс (c) = пол ((брюшной пресс (a) - b/2) / b). Затем примените знак к c.