Можете ли вы упростить этот алгоритм? - PullRequest
25 голосов
/ 19 декабря 2008

Один для математиков. Это произошло в офисе, и мы хотим посмотреть, кто может предложить более оптимизированную версию.

(((a+p) <= b) && (a == 0 || a > 1) && (b >= p)) && 
    ((b - (a + p) == 0) || (b - (a + p) > 1))

Редактировать : все данные являются положительными целыми числами

Редактировать : лучше == рефакторинг для простоты

Ответы [ 27 ]

37 голосов
/ 19 декабря 2008
(a + p <= b) && (a != 1) && (b - a - p != 1);
16 голосов
/ 19 декабря 2008

Если формула работает и исходит из ваших бизнес-правил, нет никакой реальной необходимости упрощать ее. Компилятор, вероятно, лучше нас знает, как оптимизировать формулу.

Единственное, что вам нужно сделать, - это использовать лучшие имена переменных, которые отражают бизнес-логику.

Остерегайтесь применения любого из предложенных решений перед их модульным тестированием.

5 голосов
/ 19 декабря 2008

Рефакторинг для простоты, введя больше локальных переменных, которые указывают значение каждого выражения. Это трудно для нас, не имея представления о том, что означают a, b и p.

4 голосов
/ 19 декабря 2008
b >= p && b != p+1

РЕДАКТИРОВАТЬ: Хорошо, это не сработало, но вот это:

a != 1 && b >= a+p && b-a-p != 1
4 голосов
/ 19 декабря 2008
(a!=1) && ((b==a+p) || (b>1+a+p))

Возможно, это не самое простое, но оно должно быть наиболее читабельным.

2 голосов
/ 19 декабря 2008

Поскольку все они являются положительными целыми числами, большая часть повторений может быть удалена:

Итак, в качестве первого шага,

(((a+p) <= b) && (a == 0 || a > 1) && (b >= p)) && ((b - (a + p) == 0) || (b - (a + p) > 1))

становится

((a+p) <= b) && (a != 1) && (b >= p)) && ((b - (a + p) != 1) 

Для ясности, это просто замена шаблона (foo == 0 || foo > 1) на foo != 1

Этот шаблон появляется дважды выше, один раз с foo = a и один раз с foo = (b - (a+p))

2 голосов
/ 19 декабря 2008

Я бы не делал всю математику в этом выражении. Например, b - (a + p) оценивается дважды. Если возможно, разделите их на переменные.

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

1 голос
/ 19 декабря 2008
bap = b - (a + p)
bap >= 0 && bap != 1 && a != 1

РЕДАКТИРОВАТЬ: Теперь у меня есть -2 за честную попытку помочь, а также за то, что мне кажется правильным ответом. Для вас, кто может использовать Python, вот две функции, одна с вопросом и одна с моим ответом:

def question(a, b, p):
    return (((a+p) <= b) and (a == 0 or a > 1) and (b >= p)) or ((b - (a + p) == 0) or (b - (a + p) > 1))

def answer(a, b, p):
    bap = b - (a + p)
    return bap >= 0 and bap != 1 and a != 1
1 голос
/ 19 декабря 2008

Это так просто, как я мог понять.

def calc(a, b, p):
    if (a != 1):
        temp = a - b + p
        if temp == 0 or temp < -1:
            return True
    return False

Это также может быть записано как:

def calc(a, b, p):
    temp = a - b + p
    return a != 1 and (temp == 0 or temp < -1)

Или как:

def calc(a, b, p):
    temp = a - b + p
    return a != 1 and temp <= 0 and temp != -1
1 голос
/ 20 декабря 2008

jjngy здесь имеет право. Вот доказательство того, что его упрощенная формула эквивалентна оригиналу с использованием Coq Proof Assistant .

Require Import Arith.
Require Import Omega.

Lemma eq : forall (a b p:nat),
(((a+p) <= b) /\ ((a = 0) \/ (a > 1)) /\ (b >= p)) /\ 
    ((b - (a + p) = 0) \/ (b - (a + p) > 1)) <-> 
((a + p <= b) /\ ~ (a= 1) /\ ~ (b - a - p = 1)).
Proof. intros; omega. Qed.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...