Превратить цикл с условием продолжения в математическое уравнение?

16
задан Rob 25 December 2008 в 01:19
поделиться

4 ответа

Можно доказать, что следующее корректно:

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] является отрицанием количества раз выполнения цикла, т.е.:

  • 0, если: a>-b/2 < => a+b/2> 0
  • -1, если:-b/2 ≥ a>-3b/2 < => 0 ≥ a+b/2>-b < => 0 ≥ x>-1
  • -2, если:-3b/2 ≥ a>-5b/2 < =>-b ≥ a+b/2>-2b < =>-1 ≥ x>-2 и т.д.,

, где 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 в конце второго цикла:

  • 0, если: < b/2 < => a-b/2 < 0
  • 1, если: b/2 в‰ ¤В < 3b/2 < => 0 в‰ ¤В a-b/2 < b < => 0 в‰ ¤ y < 1
  • 2, если: 3b/2 в‰ ¤В < 5b/2 < => b в‰ ¤В a-b/2 < 2b < => 1 в‰ ¤В y < 2, и т.д.,

, где 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) во всех случаях.

36
ответ дан 30 November 2019 в 16:30
поделиться
c = (int)((a - (b / 2)) / b + 1);
a -= c * b;

Тест в http://pastebin.com/m1034e639

2
ответ дан 30 November 2019 в 16:30
поделиться

Я думаю, что Вы хотите что-то вроде этого:

c = ((int) a + b / 2 * sign(a)) / b

, Который должен соответствовать Вашим циклам за исключением определенных случаев, где b нечетен, потому что диапазон от-b/2 до b/2 меньше, чем b, когда b нечетен.

1
ответ дан 30 November 2019 в 16:30
поделиться

Принятие b положительно, брюшной пресс (c) = пол ((брюшной пресс (a) - b/2) / b). Затем примените знак к c.

0
ответ дан 30 November 2019 в 16:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: