2015-03-24 1 views
-4

У меня есть 12 учетных сумм, связанных с двумя разными счетами, представленными в этом порядке: -18.91, -8.48, -3654.47, -3379.07, - 648,91, -2025,30, -1121,27, -1132,26, -22,68, -324,45, -861.50 и -24,31; из них, комбинация которых составляет сумму счета -8574,87; остальные суммы должны быть равны другой сумме счета-фактуры -4646.74. Существует ли математическая формула, которая может быть записана в COBOL для определения этого результата.Кто-нибудь знает, как написать этот алгоритм в COBOL: суммарные значения массива с суммой, равной X

01 Табличные значения таблицы Acct. 05 acct-entry встречается 50 раз 10 acct-amt PIC S9 (12) V99

01 номер таблицы счетов-фактур. 05 inv-entry происходит 50 раз 10 inv-amt PIC S9 (12) V99

+1

Код прост. Где ваш алгоритм? Сядьте с карандашом и спиной старого листинга, и придумайте, как это сделать «вручную». Затем подумайте о том, как реализовать это с кодом COBOL. Предположительно, вы находитесь на курсе, поэтому для реализации вы должны использовать методы, которые вы изучили до сих пор. Но сначала выясните, как это сделать. Код приходит позже. Я бы пошел на сумму -4646.74, возможностей будет меньше, поэтому он будет работать быстрее. Удобно сортировать данные, это просто перестановки с пределом. –

+0

Да, я смог понять это на бумаге. Мне нужна процедура в COBOL, которую моя программа может использовать для этой ситуации, которая возникает довольно часто. Это только один пример суммы денег, с которыми я сталкиваюсь, в разном порядке. -18,91 -3654,47 -648,91 -324,45 = -4646,74. – Christine

+1

Хорошая работа. Итак, вам нужно обновить свой вопрос тем, что вы придумали в псевдокоде, и показать, как вы пытались реализовать это в COBOL и где вы застряли с ним. –

ответ

2

Существует 2^12 различных комбинаций счетов. Подход Bruteforce всех комбинаций может быть реализован с использованием битовой маски (реализация COBOL будет не такой прямой), приблизительный псевдокод , чтобы получить обзор следующим образом.

for b=0 to 2^12 - 1 do #each combination 

    sum1 = 0 
    sum2= 0 
    for i=0 to 11 do # which elements are included 

    if (b && (1<<i) != 0) 
     sum1 = sum1+ arr[i+1] 
    else 
     sum2 = sum2+ arr[i+1] 
    end 
    end 
    if (sum1= -8574.87 and sum2= -4646.74) 
     print "got it" 
    end 
end 

Реализация Cobol (бесплатный формат скомпилирован и протестирован с использованием веб-компилятора). Битмаски/позиции бит вычисляются вручную (путем повторного деления на 2 и получения остатка). Следующее сочетание: -8,48 + -3379,07 + -2025,30 + -1121,27 + -1132,26 + -22,68 + -861,50 + -24,31

IDENTIFICATION DIVISION. 
PROGRAM-ID. ACCSUM. 
DATA DIVISION. 
WORKING-STORAGE SECTION. 
01 ACCOUNTS. 
    05 ACC-X  PIC S9(4)v99 COMP-3 
        OCCURS 12 TIMES. 
01 B    PIC 9(06) comp. 
01 bx    PIC 9(06) comp. 
01 pos    pic 9(06) comp. 
01 sum1   pic s9(8)v99 comp-3. 
01 sum2   pic s9(8)v99 comp-3. 
01 r    pic 9(06) comp. 
01 res    pic 9(06) comp. 
01 comb   pic x(15) value space. 

PROCEDURE DIVISION. 
0000-MAIN SECTION. 
    PERFORM 0100-init 
    perform 0200-process 
    STOP RUN. 
0100-init section. 
    move -18.91 to ACC-X(1) 
    move -8.48 to ACC-X(2) 
    move -3654.47 to ACC-X(3) 
    move -3379.07 to ACC-X(4) 
    move -648.91 to ACC-X(5) 
    move -2025.30 to ACC-X(6) 
    move -1121.27 to ACC-X(7) 
    move -1132.26 to ACC-X(8) 
    move -22.68 to ACC-X(9) 
    move -324.45 to ACC-X(10) 
    move -861.50 to ACC-X(11) 
    move -24.31 to ACC-X(12) 
    exit. 
0200-process section. 

    perform varying b from 0 by 1 
     until b>4095 
     compute bx=b 
     compute pos=0 
     move zero to sum1 sum2 
     perform until bx= zero 
      divide bx by 2 giving res remainder r 

      if (r <> zero) 
       compute sum1 = sum1+ acc-x (pos + 1) 
       move '1' to comb(pos + 1 : 1) 
      else 
       compute sum2 = sum2+ acc-x (pos + 1) 
       move '0' to comb(pos + 1 : 1) 
      end-if 

      compute bx = bx/2 
      add 1 to pos 

     end-perform 

     if (sum1 = -8574.87) then 
     display "combination :" comb "-Sum2=" sum2 
     end-if 
    end-perform 
    exit. 
+0

Если вы хотите сделать некоторое COBOL в свое время, посмотрите GnuCOBOL на SourceForge. Гораздо более гибкий, чтобы иметь свои собственные. GnuCOBOL ранее был OpenCOBOL, который вполне может быть тем, что вы использовали в Интернете. –

+0

Это хорошая идея. Я полагаю, вы знаете, как это работает. Если две искомые суммы равны нулю и сумме всех 12, так что ваше значение поиска равно нулю, оно не будет выполнено. Не большая проблема, как если бы одна из ожидаемых сумм была равна нулю, вы можете легко сократить все это. Если запрашиваются три суммы или n-суммы, их все равно можно заставить работать (base-3 или base-n). Он опирается на все индивидуальные ценности, составляющие в настоящий момент, но даже с этим можно справиться. Он найдет множество решений для комбинаций значений. –

+0

В вашем COBOL есть некоторые вещи. Я предполагаю, что вы довольно новичок в COBOL, но знакомы с другими языками? Вы делите bx на два раза. Используя решение, в котором позиции закодированы, нет необходимости хранить их по мере продвижения, но используйте текущее значение b и де-код, который. Ваши два оставшихся ВЫЧИСЛЕНИЯ лучше, чем простые ДОБАВКИ. Чтобы избежать пропусков, о которых я упоминал, начните свой внешний цикл с 1 (и добавьте один к значению терминала). Также можно избежать, делая внутренний цикл другим способом, например 12 TIMES. Внешняя петля может быть 4096 раз и управлять b самостоятельно. –