home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / LONGINT.ZIP / DERSH1.PAS
Encoding:
Pascal/Delphi Source File  |  1988-10-24  |  11.2 KB  |  405 lines

  1. program project1(input,output);
  2. {This program fulfills the requirements of Project 1 in CSCI 220 - Fall 1988.
  3.  It permits the entry, printing, addition, and subtraction of long integers.
  4.  Author: Herbert L. Dershem
  5.  Date  : October 21, 1988
  6.  Program Title: Long Integers}
  7.  
  8. const maxlen = 80;  {Maximum length of a number}
  9. type numstring = varying [maxlen + 1] of char;  {representing long integers}
  10.      string = varying [80] of char;             {representing character strings}
  11.      intarray = array [1..maxlen] of integer;   {integer representation of long
  12.                                                  integers}
  13.      longnum = record            {longnum is the internal form of long integers}
  14.                  sign:char;
  15.                  whole:intarray;
  16.                  fraction:intarray;
  17.                end;
  18.      vararray = array ['A'..'Z'] of longnum; {array of longnum variables}
  19.  
  20. var v:vararray;          {variable array}
  21.     selection:integer;   {menu selection}
  22.  
  23. procedure initialize(var v:vararray);
  24. {Initialize the variable array to sign of *}
  25. var c:char;
  26. begin
  27.   for c:='A' to 'Z' do
  28.     v[c].sign:='*';
  29. end; {initialize}
  30.  
  31. procedure presentmenu;
  32. {Present the menu to the user}
  33. begin
  34.   writeln('1. Enter a number');
  35.   writeln('2. Print a number');
  36.   writeln('3. Add numbers');
  37.   writeln('4. Subtract numbers');
  38.   writeln('5. Terminate program');
  39.   writeln;
  40. end; {presentmenu}
  41.  
  42. procedure menuselect(var selection:integer);
  43. {Make a legal selection from the menu.  Prompts for entry will continue until
  44.  a legal entry (1-5) is made.}
  45. var c:char;
  46. begin
  47.   presentmenu;
  48.   write('Enter your selection: ');
  49.   readln(c);
  50.   while not (c in ['1'..'5']) do
  51.   begin
  52.     writeln('Illegal entry - enter an integer from 1 to 5');
  53.     write('Enter you selection: ');
  54.     readln(c);
  55.   end;
  56.   selection := ord(c) - ord('0');
  57. end; {menuselect}
  58.  
  59. function upper(c:char):char;
  60. {If c is a lower case letter, change to upper case.  Otherwise return c 
  61.  unchanged.}
  62. begin
  63.   if c in ['a'..'z'] then
  64.     upper := chr(ord(c) + ord('A') - ord('a'))
  65.   else
  66.     upper := c;
  67. end; {upper}
  68.  
  69. procedure getvar(comment:string; var vname:char);
  70. {Use comment to prompt for a variable name and return a legal name ('A'..'Z').
  71.  Procedure will continue to prompt until a legal entry is made.  Lower case
  72.  letters will be converted to legal upper case letters.}
  73. begin
  74.   write('What variable do you wish to '+comment+'?');
  75.   readln(vname);
  76.   vname := upper(vname);
  77.   while not (vname in ['A'..'Z']) do
  78.   begin
  79.     writeln('Illegal entry - enter a letter from A to Z');
  80.     readln(vname);
  81.     vname := upper(vname);
  82.   end;
  83. end; {getvar}
  84.  
  85. procedure split(strvalue:numstring; var strwhole,strfraction:numstring);
  86. {Take the string version in strvalue and split it into the whole and 
  87.  fractional strings, i.e., those digits before and after the decimal point.}
  88. var point:integer;
  89. begin
  90.   point:=index(strvalue,'.');
  91.   if point > 0 then
  92.   begin
  93.     strwhole := substr(strvalue,1,point-1);
  94.     strfraction := substr(strvalue,point+1,length(strvalue)-point);
  95.   end
  96.   else
  97.   begin
  98.     strwhole := strvalue;
  99.     strfraction := '0';
  100.   end;
  101. end; {split}
  102.  
  103. procedure convertwhole(strwhole:numstring; var value:longnum; var valid:boolean);
  104. {Convert the whole part string in strwhole into it integer array equivalent in
  105.  value.  Valid indicates whether strwhole was valid or not.}
  106. var loc,i:integer;
  107. begin
  108.   valid := true;
  109.   loc := 0;
  110.   for i:=length(strwhole) downto 1 do
  111.     if valid and (strwhole[i] in ['0'..'9']) then
  112.     begin
  113.       loc := loc + 1;
  114.       value.whole[loc] := ord(strwhole[i])-ord('0');
  115.     end
  116.     else
  117.       valid := false;
  118.   if valid then
  119.     for i := loc+1 to maxlen do
  120.       value.whole[i] := 0;
  121. end; {convertwhole}
  122.  
  123. procedure convertfraction(strfraction:numstring; var value:longnum; var valid:
  124.                                                   boolean);
  125. {Convert the fraction string in strfraction to its integer array equivalent
  126.  in value.  Valid indicates whether strfraction represents a valid fraction or
  127.  not.}
  128. var i,loc:integer;
  129. begin
  130.   valid:=true;
  131.   for loc :=1 to length(strfraction) do
  132.     if valid and (strfraction[loc] in ['0'..'9']) then
  133.       value.fraction[loc] := ord(strfraction[loc]) - ord('0')
  134.     else
  135.       valid := false;
  136.   if valid then
  137.     for i := length(strfraction)+1 to maxlen do
  138.       value.fraction[i]:=0;
  139. end; {convertfraction}
  140.  
  141. procedure getnum(vname:char; var value:longnum);
  142. {Requests a long number for variable vname from the user and tests it 
  143. for validity.  The valid number is stored in value.}  
  144. var strvalue,strwhole,strfraction:numstring;
  145.     valid:boolean;
  146. begin
  147.   writeln('What value do you wish to enter for '+vname+'?');
  148.   readln(strvalue);
  149.   if length(strvalue)>maxlen then
  150.   begin
  151.     writeln('Number too long - please try again - max is ',maxlen:1);
  152.     getnum(vname,value);
  153.   end
  154.   else
  155.   begin
  156.     if length(strvalue)>0 then
  157.     begin
  158.     if (strvalue[1]='-') or (strvalue[1]='+') then
  159.     begin
  160.       value.sign := strvalue[1];
  161.       strvalue := substr(strvalue,2,length(strvalue)-1);
  162.     end
  163.     else
  164.       value.sign := '+';
  165.     end;
  166.     split(strvalue,strwhole,strfraction);
  167.     convertwhole(strwhole,value,valid);
  168.     if valid then
  169.       convertfraction(strfraction,value,valid);
  170.     if not valid then
  171.     begin
  172.       writeln('Invalid number - try again');
  173.       getnum(vname,value);
  174.     end;
  175.   end;
  176. end; {getnum}
  177.  
  178. procedure enter(var v:vararray);
  179. {Prompts for an entry of a number by requesting the variable name and number
  180.  and stores the entered number in the variable.}
  181. var vname:char;
  182. begin
  183.   getvar('enter',vname);
  184.   getnum(vname,v[vname]);
  185. end; {enter}
  186.  
  187. procedure printvar(value:longnum);
  188. {Prints the value}
  189. var charcount,loc,last:integer;
  190.     leftsignificant:boolean;
  191.     rightsignificant:boolean;
  192. begin
  193.   charcount:=0;
  194.   leftsignificant := false;
  195.   if value.sign='-' then
  196.   begin
  197.     write('-');
  198.     charcount:=1;
  199.   end;
  200.   for loc := maxlen downto 1 do
  201.     if (value.whole[loc]<>0) or (leftsignificant) then
  202.     begin
  203.       leftsignificant := true;
  204.       write(chr(value.whole[loc] + ord('0')));
  205.       charcount:=charcount + 1;
  206.     end;
  207.   rightsignificant := false;
  208.   last:=0;
  209.   for loc := maxlen downto 1 do
  210.     if (not rightsignificant) and (value.fraction[loc]>0) then
  211.     begin
  212.       last := loc;
  213.       rightsignificant := true;
  214.     end;
  215.   if (last>0) and (charcount<maxlen) then
  216.   begin
  217.     write('.');
  218.     if last-charcount>maxlen-1 then
  219.       last:=maxlen-1-charcount;
  220.     for loc:=1 to last do
  221.       write(chr(value.fraction[loc] + ord('0')));
  222.   end;
  223.   if not(rightsignificant or leftsignificant) then
  224.     write('0');
  225.   writeln;
  226. end; {printvar}
  227.  
  228. procedure print(v:vararray);
  229. {Prompts user for variable name and prints that variable.}
  230. var vname:char;
  231. begin
  232.   getvar('print',vname);
  233.   printvar(v[vname]);
  234. end; {print}
  235.  
  236. function gtr(value1,value2:longnum):boolean;
  237. {Returns true if value1 is greater than value2.}
  238. var loc:integer;
  239. begin
  240.   loc:=maxlen;
  241.   while (loc>1) and (value1.whole[loc]=value2.whole[loc]) do
  242.     loc:=loc-1;
  243.   if value1.whole[loc]=value2.whole[loc] then
  244.   begin
  245.     loc:=1;
  246.     while (loc<maxlen) and (value1.fraction[loc]=value2.fraction[loc]) do
  247.       loc:=loc+1;
  248.     gtr:=value1.fraction[loc]>value2.fraction[loc];
  249.   end
  250.   else
  251.     gtr:=value1.whole[loc]>value2.whole[loc];
  252. end; {gtr}
  253.  
  254. procedure sumdigit(digit1,digit2:integer; var answer,carry:integer);
  255. {Adds digit1 and digit2 and places resulting digit in answer and carry in carry.}
  256. begin
  257.   answer:=digit1+digit2+carry;
  258.   if answer>9 then
  259.   begin
  260.     answer:=answer-10;
  261.     carry:=1;
  262.   end
  263.   else
  264.     carry:=0;
  265. end; {sumdigit}
  266.  
  267. procedure subdigit(digit1,digit2:integer; var answer,carry:integer);
  268. {Subtracts digit2 from digit1 and places resulting digit in answer and carry in
  269.  carry.  If there is a carry, it is -1.}
  270. begin
  271.   answer:=digit1-digit2+carry;
  272.   if answer<0 then
  273.   begin
  274.     answer:=answer+10;
  275.     carry:=-1;
  276.   end
  277.   else
  278.     carry:=0;
  279. end; {subdigit}
  280.  
  281. function numsigs(value:longnum):integer;
  282. {Returns the number of significant digits in value including sign and decimal.}
  283. var left,right,count:integer;
  284. begin
  285.   left:=maxlen;
  286.   while (left>1) and (value.whole[left]=0) do
  287.     left:=left-1;
  288.   if value.whole[left]=0 then
  289.     left:=0;
  290.   right:=maxlen;
  291.   while (right>1) and (value.fraction[right]=0) do
  292.     right:=right-1;
  293.   if value.fraction[right]=0 then
  294.     right:=0;
  295.   count:=0;
  296.   if right>0 then count:=count+1;
  297.   if value.sign='-' then count:=count+1;
  298.   numsigs:=left+right+count;
  299. end; {numsigs}
  300.  
  301. procedure negate(var value:longnum);
  302. {Changes the sign of value.}
  303. begin
  304.   if value.sign='-' then value.sign:='+'
  305.                     else value.sign:='-';
  306. end; {negate}
  307.  
  308. procedure diff(value1,value2:longnum; var value3:longnum);
  309. {Stores the difference value1-value2 in value3}
  310. var valtemp:longnum;
  311.     i,carry:integer;
  312. begin
  313.   if gtr(value2,value1) then
  314.   begin
  315.     negate(value1);
  316.     negate(value2);
  317.     diff(value2,value1,value3);
  318.   end
  319.   else
  320.   begin
  321.     carry:=0;
  322.     valtemp.sign:=value1.sign;
  323.     for i:=maxlen downto 1 do
  324.       subdigit(value1.fraction[i],value2.fraction[i],valtemp.fraction[i],
  325.                carry);
  326.     for i:=1 to maxlen do
  327.       subdigit(value1.whole[i],value2.whole[i],valtemp.whole[i],carry);
  328.     if numsigs(valtemp)>maxlen then
  329.       writeln('Answer not representible in ',maxlen,' characters.')
  330.     else
  331.       value3:=valtemp;
  332.   end;
  333. end; {diff}
  334.  
  335. procedure sum(value1,value2:longnum; var value3:longnum);
  336. {Stores the sum value1+value2 in value3}
  337. var valtemp:longnum;
  338.     i,carry:integer;
  339. begin
  340.   if value1.sign='*' then
  341.     writeln('First operand is undefined')
  342.   else if value2.sign='*' then
  343.     writeln('Second operand is undefined')
  344.   else
  345.   begin
  346.     if value1.sign<>value2.sign then
  347.     begin
  348.       negate(value2);
  349.       diff(value1,value2,value3);
  350.     end
  351.     else
  352.     begin
  353.       carry:=0;
  354.       valtemp.sign:=value1.sign;
  355.       for i:= maxlen downto 1 do
  356.         sumdigit(value1.fraction[i],value2.fraction[i],valtemp.fraction[i],
  357.                  carry);
  358.       for i := 1 to maxlen do
  359.         sumdigit(value1.whole[i],value2.whole[i],valtemp.whole[i],carry);
  360.       if numsigs(valtemp)>maxlen then
  361.         writeln('Answer not representable in ',maxlen,' characters')
  362.       else
  363.         value3:=valtemp;
  364.     end;
  365.   end;
  366. end; {sum}
  367.  
  368. procedure add(var v:vararray);
  369. {Prompts for add and carries out the addition.}
  370. var vname1,vname2,vname3:char;
  371. begin
  372.   getvar('add first',vname1);
  373.   getvar('add second',vname2);
  374.   getvar('hold the result',vname3);
  375.   sum(v[vname1],v[vname2],v[vname3]);
  376. end; {add}
  377.  
  378. procedure subtract(var v:vararray);
  379. {Prompts for subtraction and carries it out.}
  380. var vname1,vname2,vname3:char;
  381. begin
  382.   getvar('subtract from',vname1);
  383.   getvar('subtract',vname2);
  384.   getvar('hold the result',vname3);
  385.   negate(v[vname2]);
  386.   sum(v[vname1],v[vname2],v[vname3]);
  387.   negate(v[vname2]);
  388. end; {subtract}
  389.  
  390. begin {main}
  391.  initialize(v);
  392.  repeat
  393.   repeat
  394.     menuselect(selection);
  395.   until (selection>=1) and (selection<=5);
  396.   if selection <5 then
  397.     case selection of
  398.      1: enter(v);
  399.      2: print(v);
  400.      3: add(v);
  401.      4: subtract(v);
  402.     end; {case}
  403.  until selection=5;  
  404. end.
  405.