identificationdivision. program-id. CALC. author. Robert Wagner date-written. 07/29/04 * Huge number function library. * Parses formula out of a string. * Runs three ways: * From command line -- type in formula * Call CALCPARS -- to parse and evaluate formula * Call CALCxxxx low-level functions * * Negative numbers are nines complement. * The left half contains the 'whole number' and the right * half contains the * fraction. * * Note that everything is relative to the size of 'huge' * below. * The program would read better if I could equate * 'mid' to 'length of huge / 2'. I couldn *'t find a way in Cobol 85.
linkagesection
01 a huge.
01 b huge.
01 c huge.
01 input-string.
05 input-byte occurs 128 indexed x-in pic x(01).
* Compiler insists on this USING. There are no parms to main. PROCEDUREDIVISIONusing a, b, c, input-string. move low-values to typein performuntil typein equaltospaces display'Enter problem' accept typein move zeros to x, y, z
call'CALCPARS'using x, y, z, typein
display'the answer is: 'withnoadvancing call'DISPC'using x, y, z end-perform stoprun
. entry'CALCPARS'using a, b, c, input-string. move a to x move b to y move zeros to a, b, c move 1 to sp move zeros to stack-number (1) move'+'to stack-operation (1) set x-in to 1 perform one-word until x-in greaterthan 128 if sp notequalto 1 display'too many left parens' perform do-operation until sp = 1 end-if move stack-number (1) to c
goback
. one-word. evaluate input-byte (x-in) when = '+'or'-'or'*'or'/'or'^'or'!' move input-byte (x-in) to stack-operation (sp) if input-byte (x-in) equalto'!' perform do-operation movespaceto stack-operation (sp) end-if when'0' thru '9' when'.' perform pickup-number perform process-number when'(' perform bump-sp move zeros to stack-number (sp) move'+'to stack-operation (sp) when')' perform do-operation when'a' move x to b perform process-number when'b' move y to b perform process-number whenspace continue whenother set i to x-in display'invalid input ' input-byte (x-in) ' col ' i end-evaluate set x-in upby 1
. pickup-number. move zeros to b compute p = lengthof huge / 2 performuntil (input-byte (x-in) less'0'orgreater'9') and
input-byte (x-in) notequalto'.' if input-byte (x-in) equalto'.' compute p = (lengthof huge / 2) + 1 else if p equalto (lengthof huge / 2) call'CALCSHL'using a, b, c move input-byte (x-in) to a-digit in b (lengthof huge / 2) else move input-byte (x-in) to a-digit in b (p) add 1 to p end-if end-if set x-in upby 1 end-perform set x-in downby 1
. process-number. perform bump-sp move b to stack-number (sp) perform do-operation
. do-operation. if debug-mode if stack-operation (sp) notequalto'!' perform dec-sp end-if move stack-number (sp) to c perform display-c display stack-operation (sp) if stack-operation (sp) notequalto'!' perform bump-sp move stack-number (sp) to c perform display-c end-if end-if
move stack-number (sp) to b if stack-operation (sp) notequalto'!' perform dec-sp move stack-number (sp) to a end-if evaluate stack-operation (sp) when'+' call'CALCADD'using a, b, c when'-' call'CALCSUB'using a, b, c when'*' call'CALCMUL'using a, b, c when'/' call'CALCDIV'using a, b, c when'^' call'CALCEXP'using a, b, c when'!' call'CALCFAC'using a, b, c whenother move b to c end-evaluate move c to stack-number (sp)
if debug-mode display'=' perform display-c end-if
bump-sp. if sp lessthan 10 add 1 to sp else display'stack overflow' end-if
dec-sp. if sp greaterthan 1 subtract 1 from sp else display'too many right parens' end-if
display-c. if a-digit in c (1) equalto 9 call'CALCNEG'using a, b, c display'-'withnoadvancing end-if performvarying i from 1 by 1 until
a-digit in c (i) not = zeroor i > 99 continue end-perform performvarying i from i by 1 until i > ((lengthof huge /
2) + 20) or
(i equalto ((lengthof huge / 2) + 1) and
c((lengthof huge / 2) + 1:lengthof huge / 2) equaltozero) display a-digit in c (i) withnoadvancing if i equalto (lengthof huge / 2) display'.'withnoadvancing end-if end-perform displayspace
end-calcpars
* Begin calchuge. entry'CALCADD'using a, b, c. perform compute-a-plus-b goback entry'CALCSUB'using a, b, c. perform compute-a-minus-b goback entry'CALCMUL'using a, b, c. perform compute-a-times-b goback entry'CALCDIV'using a, b, c. perform compute-a-divided-by-b goback entry'CALCEXP'using a, b, c. if b(1:(lengthof huge / 2) - 2) equaltozeroand
b((lengthof huge / 2) + 1:lengthof huge / 2) equaltozero perform compute-a-ipower-b else perform compute-a-power-b end-if goback entry'CALCFAC'using a, b, c. perform compute-b-factorial goback entry'CALCNEG'using a, b, c. perform flip-sign-c goback entry'CALCSHR'using a, b, c. perform shift-b-right goback entry'CALCSHL'using a, b, c. perform shift-b-left goback entry'DISPC'using a, b, c. perform display-c goback
compute-a-plus-b. movezeroto overflow-digit if 9 not = a-digit in b (1) and a-digit in a (1) move 0 to overflow-digit perform add-operation else if 9 = a-digit in b (1) and a-digit in a (1) move 1 to overflow-digit perform add-operation else perform flip-sign-b perform compute-a-minus-b end-if
add-operation. performvarying i fromlengthof huge by -1 until i less than 1 compute temp-s =
a-digit in a (i) + a-digit in b (i) + overflow-digit if temp-s lessthan 10 move temp-s to a-digit in c (i) move 0 to overflow-digit else subtract 10 from temp-s giving a-digit in c (i) move 1 to overflow-digit end-if end-perform
compute-a-minus-b. movezeroto overflow-digit if b greaterthan a move 1 to overflow-digit end-if performvarying i fromlengthof huge by -1 until i less than 1 compute temp-s =
a-digit in a (i) - a-digit in b (i) - overflow-digit if temp-s lessthanzero add 10 to temp-s giving a-digit in c (i) move 1 to overflow-digit else move temp-s to a-digit in c (i) move 0 to overflow-digit end-if end-perform
compute-a-times-b. perform normalize-sign-in move zeros to d performvarying i fromlengthof huge by -1 until i less than 1 if a-digit in b (i) notequaltozero compute k = i + (lengthof huge / 2) performvarying j fromlengthof huge by -1 until j less than 1 if a-digit in a (j) notequaltozeroand
k notless 1 andnotgreaterlengthof huge compute two-digits =
a-digit in a (j) * a-digit in b (i) perform add-two-digits end-if subtract 1 from k end-perform end-if end-perform move d to c perform normalize-sign-out
compute-a-divided-by-b. perform normalize-sign-in compute k = lengthof huge / 2 performuntil b notlessthan a or k = 1 perform shift-b-left subtract 1 from k end-perform move zeros to d performuntil k > lengthof huge performuntil b greaterthan a or b = zeros move 1 to two-digits perform add-two-digits perform compute-a-minus-b move c to a end-perform perform shift-b-right add 1 to k end-perform move d to c perform normalize-sign-out
compute-a-power-b. * Computing a^b move a to temp-a move b to temp-b if a-digit in a (1) equalto 9 or a equaltozero movezeroto c exit paragraph end-if * Get the exponent by repeatedly dividing by e movezeroto e, exponent move'27182818284590452353602874'to e(lengthof huge / 2:26) performuntil temp-a notgreaterthan e move temp-a to a move e to b perform compute-a-divided-by-b move c to temp-a move exponent to a movezeroto b move 1 to a-digit in b (lengthof huge / 2) perform compute-a-plus-b move c to exponent end-perform * Compute base e logarithm of the mantissa * ln(x) = perform varying t from 1 by 2 until delta = zero * or t > 90 * compute ln = ln + ((2 / t) * (((x - 1) / (x + 1)) ^ t)) * where 0 < x < e move temp-a to a movezeroto b move 1 to a-digit in b (lengthof huge / 2) perform compute-a-minus-b move c to temp-2 perform compute-a-plus-b move temp-2 to a move c to b perform compute-a-divided-by-b move c to temp-2 *> save (x - 1) / (x + 1) movezeroto temp-3 moveall'1'to b performvarying term from 1 by 2 until
b(1:(lengthof huge / 2) + 16) = zeroor term > 90 or
b(1:(lengthof huge / 2) + 16) = all'9' movezeroto a, b move 2 to a-digit in a (lengthof huge / 2) move term to b((lengthof huge / 2) - 1:2) perform compute-a-divided-by-b move c to temp-1 move temp-2 to a movezeroto b move term to b((lengthof huge / 2) - 1:2) perform compute-a-ipower-b move temp-1 to a move c to b perform compute-a-times-b move temp-3 to a move c to b perform compute-a-plus-b move c to temp-3 end-perform * Add the exponent giving ln(a) move c to a move exponent to b perform compute-a-plus-b * Multiply by b move c to a move temp-b to b perform compute-a-times-b move c to temp-a * e^x = perform varying t from 1 by 1 until delta = zero or * t > 90 * compute exp = exp + ((x ^ t) / t!) * add 1 to exp * Note that ln(a) will be negative when a < 1. In that case, * this is * an alternating series because n^t will be negative half * the time. movezeroto b move 1 to a-digit in b (lengthof huge / 2) move b to temp-3 performvarying term from 1 by 1 until
b(1:(lengthof huge / 2) + 16) = zeroor term > 90 move temp-a to a movezeroto b move term to b((lengthof huge / 2) - 1:2) perform compute-a-ipower-b move c to temp-1 movezeroto b move term to b((lengthof huge / 2) - 1:2) perform compute-b-factorial move temp-1 to a move c to b perform compute-a-divided-by-b move temp-3 to a move c to b perform compute-a-plus-b move c to temp-3 end-perform * Discard meaningless digits if c ((lengthof huge / 2) + 17:(lengthof huge / 2) - 16) notequaltozero move c to a movezeroto b move 5 to a-digit in b ((lengthof huge / 2) + 17) perform compute-a-plus-b movezeroto c((lengthof huge / 2) + 17:(lengthof huge /
2) - 16) end-if if c((lengthof huge / 2) + 1:6) equaltozeroand
c(1:(lengthof huge / 2)) notequaltozero movezeroto c((lengthof huge / 2) + 7:(lengthof huge / 2)
- 6) end-if
* Integer exponent 1-99
compute-a-ipower-b. move b((lengthof huge / 2) - 1:2) to two-digits move two-digits to power move zeros to b move 1 to a-digit in b (lengthof huge / 2) perform power times perform compute-a-times-b move c to b end-perform if c((lengthof huge / 2) + 1:10) equaltozeroand
c(1:(lengthof huge / 2)) notequaltozero movezeroto c((lengthof huge / 2) + 11:(lengthof huge /
2) - 10) end-if
compute-b-factorial. move b((lengthof huge / 2) - 1:2) to two-digits move two-digits to power move zeros to a, b move 1 to a-digit in a (lengthof huge / 2),
a-digit in b (lengthof huge / 2) performvarying factorial from 1 by 1 until factorial > power move factorial to two-digits move two-digits to b((lengthof huge / 2) - 1:2) perform compute-a-times-b move c to a end-perform
flip-sign-a. inspect a converting'0123456789' to'9876543210'
flip-sign-b. inspect b converting'0123456789' to'9876543210'
flip-sign-c. inspect c converting'0123456789' to'9876543210'
shift-b-right. move b(1:lengthof huge - 1) to shifter(2:lengthof huge - 1) movezeroto shifter(1:1) move shifter to b
shift-b-left. move b(2:lengthof huge - 1) to shifter(1:lengthof huge - 1) movezeroto shifter(lengthof huge:1) move shifter to b
add-two-digits. move k to l performuntil two-digits = zeroor l < 1 add a-digit in d (l) to two-digits move digit-2 to a-digit in d (l) move digit-1 to digit-2 move 0 to digit-1 subtract 1 from l end-perform
normalize-sign-in. movezeroto sign-count if a-digit in a (1) equalto 9 add 1 to sign-count perform flip-sign-a end-if if a-digit in b (1) equalto 9 add 1 to sign-count perform flip-sign-b end-if
normalize-sign-out. if sign-count equalto 1 perform flip-sign-c end-if
Messung V0.5
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.