Skip to content

Instantly share code, notes, and snippets.

@JamesEarle
Created February 11, 2014 17:27
Show Gist options
  • Save JamesEarle/8939661 to your computer and use it in GitHub Desktop.
Save JamesEarle/8939661 to your computer and use it in GitHub Desktop.
Rational Number Calculator
with
Ada.Text_IO,
Ada.Strings,
Ada.Strings.Fixed,
RATIONALS;
use
Ada.Text_IO,
Ada.Strings,
Ada.Strings.Fixed,
RATIONALS;
procedure rationalcalc is
A, B, C : RATIONAL;
Check : Boolean;
procedure Start is
type My_Float is digits 9;
A, B, C : RATIONAL;
Char : Character;
Check : Boolean;
F : My_Float;
begin
Put_Line("Welcome to the Rational Numbers Calculator!");
Put("Please include '.' after each operand (e.g. 'A/B.')");
New_Line(1);
Put("Type 'EXIT.' to leave the program, or type 'HELP.' to see a list of operators. ");
Put_Line("Order of input is: First Operand, Operator, Second Operand.");
New_Line(1);
A := RAT(1,1); --Initialize the A value, to be overwritten
while DENOM(A) /= 9999 loop
Put("O1: ");
GET_IN(A);
if DENOM(A) /= 9999 and DENOM(A) /= 8888 then
Put("Op: ");
Get(Char);
Put("O2: ");
GET_IN(B);
case Char is
when '+' =>
C := A+B;
New_Line(1);
Put("= ");
C := NORMAL(C);
PUT_OUT(C);
Put("= ");
F := My_Float(NUMER(C))/My_Float(DENOM(C));
Put(Trim(My_Float'Image(F),Both));
New_Line(1);
when '-' =>
C := A-B;
New_Line(1);
Put("= ");
C := NORMAL(C);
PUT_OUT(C);
Put("= ");
F := My_Float(NUMER(C))/My_Float(DENOM(C));
Put(Trim(My_Float'Image(F),Both));
New_Line(1);
when '*' =>
C := A*B;
New_Line(1);
Put("= ");
C := NORMAL(C);
PUT_OUT(C);
Put("= ");
F := My_Float(NUMER(C))/My_Float(DENOM(C));
Put(Trim(My_Float'Image(F),Both));
New_Line(1);
when '/' =>
C := A/B;
New_Line(1);
Put("= ");
C := NORMAL(C);
PUT_OUT(C);
Put("= ");
F := My_Float(NUMER(C))/My_Float(DENOM(C));
Put(Trim(My_Float'Image(F),Both));
New_Line(1);
when '<' =>
Check := LE(A,B);
New_Line(1);
Put("= ");
Put_Line(Boolean'Image(Check));
New_Line(1);
when '>' =>
Check := GE(A,B);
New_Line(1);
Put("= ");
Put_Line(Boolean'Image(Check));
New_Line(1);
when '=' =>
Check := A=B;
New_Line(1);
Put("= ");
Put_Line(Boolean'Image(Check));
New_Line(1);
when others =>
Put_Line("Please enter a valid operation.");
end case;
end if;
end loop;
end start;
begin
Start;
New_Line(1);
Put_Line("Tests of every procedure and function below.");
New_Line(1);
Put("Provide a rational number (A/B.): ");
GET_IN(A);
New_Line(1);
Put("You entered: ");
PUT_OUT(A);
A := RAT(3,4);
B := RAT(5,8);
Put_Line("Testing arithmetic below. A = 3/4. B = 5/8.");
C := A+B;
Put("A + B = ");
PUT_OUT(C);
C := A-B;
Put("A - B = ");
PUT_OUT(C);
C := A*B;
Put("A * B = ");
PUT_OUT(C);
C := A/B;
Put("A / B = ");
PUT_OUT(C);
Check := A=B;
Put_Line("A = B returns " & Boolean'Image(Check));
Check := NE(A,B);
Put_Line("A != B returns " & Boolean'Image(Check));
Check := LT(A,B);
Put_Line("A < B returns " & Boolean'Image(Check));
Check := LE(A,B);
Put_Line("A <= B returns " & Boolean'Image(Check));
Check := GT(A,B);
Put_Line("A > B returns " & Boolean'Image(Check));
Check := GE(A,B);
Put_Line("A >= B returns " & Boolean'Image(Check));
A := RAT(24,10);
Put_Line("Testing the NORMAL function. A = 24/10");
A := NORMAL(A);
Put("After call to NORMAL, A = ");
PUT_OUT(A);
end rationalcalc;
with
Ada.Text_IO,
Ada.Strings,
Ada.Strings.Fixed,
RATIONALS;
use
Ada.Text_IO,
Ada.Strings,
Ada.Strings.Fixed,
RATIONALS;
-- End Packages --
package body RATIONALS is
function RAT (N, D : INTEGER) return RATIONAL is
Result : RATIONAL;
begin
if D = 0 then
raise RATIONAL_ERROR;
else
Result := RATIONAL'( N, D );
end if;
return Result;
exception
when RATIONAL_ERROR =>
Put_Line("RATIONAL_ERROR: Denominator cannot be zero.");
raise;
end RAT; -- Returns the given rational number from GET_IN
function NUMER(R : RATIONAL) return INTEGER is
begin
return R.NUM;
end NUMER; -- returns numerator
function DENOM (R : RATIONAL) return INTEGER is
begin
return R.DEN;
end DENOM; -- returns denominator
procedure GET_IN (R : out RATIONAL) is
type Input_String is array (Integer range 1..20) of Character;
Str : Input_String := (others => ' ');
Ctr : Integer := 1;
S : String(1..20) := (others => ' ');
C : Character;
T1 : String(1..20) := (others => ' ');
T2 : String(1..20) := (others => ' ');
Exit_String : Input_String := "EXIT ";
Help_String : Input_String := "HELP ";
Check : Boolean := False;
Numerator, Denominator : Integer;
begin
while Ctr < Str'Last loop
Get(C);
exit when C = '.';
Str(Ctr) := C;
S(Ctr) := Str(Ctr);
Ctr := Ctr + 1;
end loop;
if Str = Help_String then
New_Line(1);
Put_Line("Below are the possible operators.");
Put_Line("+, -, *, /, <, >, =, <=, >=, !=");
R.NUM := 0;
R.DEN := 8888;
return;
end if;
if Str = Exit_String then
New_Line(1);
Put_Line("Thank you for using the Rationals Calculator!");
R.NUM := 0;
R.DEN := 9999;
return;
end if;
for I in Integer range 1..(Ctr-1) loop
if S(I) = '/' then
Check := True;
else
if Check = False then
T1(I) := S(I);
else
T2(I) := S(I);
end if;
end if;
end loop;
Numerator := Integer'Value(T1);
Denominator := Integer'Value(T2);
if Denominator = 0 then
raise RATIONAL_ERROR;
else
R.NUM := Numerator;
R.DEN := Denominator;
end if;
exception
when RATIONAL_ERROR =>
Put_Line("RATIONAL_ERROR: Denominator cannot be zero.");
raise;
end GET_IN; -- inputs rational number from keyboard
procedure PUT_OUT (R : in RATIONAL) is
Result : RATIONAL;
begin
Result := R;
if Result.NUM = Result.DEN then
Put_Line("1");
New_Line(1);
elsif Result.NUM = 0 then
Put_Line("0");
New_Line(1);
elsif Result.DEN = 1 then
Put_Line(Trim(Integer'Image(R.NUM),Both));
New_Line(1);
else
Put_Line(Trim(Integer'Image(R.NUM),Both) & "/" & Trim(Integer'Image(R.DEN),Both));
New_Line(1);
end if;
end PUT_OUT; -- outputs rational number (normalized) to screen
-- Rational Arithmetic Procedures (may raise RATIONAL_ERROR if necessary):
function NORMAL (R : RATIONAL) return RATIONAL is
Result : RATIONAL;
M : Integer := R.NUM;
N : Integer := R.DEN;
T, LCM : Integer;
begin
Result := R;
if Result.NUM = Result.DEN then
Result.NUM := 1;
Result.DEN := 1;
end if;
while (Result.NUM rem 2 = 0 and Result.DEN rem 2 = 0) loop
Result.NUM := Result.NUM / 2;
Result.DEN := Result.DEN / 2;
end loop;
if Result.NUM mod Result.DEN = 0 then
Result.NUM := Result.NUM / Result.DEN;
Result.DEN := 1;
end if;
return Result;
end NORMAL; -- normalizes rational number R
function "+" (X, Y : RATIONAL) return RATIONAL is
Result : RATIONAL;
N1,D1,N2,D2 : Integer;
begin
N1 := X.NUM * Y.DEN;
D1 := X.DEN * Y.DEN;
N2 := Y.NUM * X.DEN;
D2 := Y.DEN * X.DEN;
Result.NUM := N1 + N2;
Result.DEN := D2;
Result := NORMAL(Result);
return Result;
end "+";
function "-" (X, Y : RATIONAL) return RATIONAL is
Result : RATIONAL;
N1,D1,N2,D2 : Integer;
begin
N1 := X.NUM * Y.DEN;
D1 := X.DEN * Y.DEN; -- 3/9
N2 := Y.NUM * X.DEN;
D2 := Y.DEN * X.DEN; -- 6/9
Result.NUM := N1 - N2;
Result.DEN := D2;
Result := NORMAL(Result);
return Result;
end "-";
function "*" (X, Y : RATIONAL) return RATIONAL is
Result : Rational;
N1,D1,N2,D2 : Integer;
begin
N1 := X.NUM;
D1 := X.DEN;
N2 := Y.NUM;
D2 := Y.DEN;
Result.NUM := N1 * N2;
Result.DEN := D1 * D2;
Result := NORMAL(Result);
return Result;
end "*";
function "/" (X, Y : RATIONAL) return RATIONAL is
Result, Reciprocal : RATIONAL;
N,D : Integer;
begin
N := Y.NUM;
D := Y.DEN;
Reciprocal.NUM := D;
Reciprocal.DEN := N;
Result := X*Reciprocal;
Result := NORMAL(Result);
return Result;
end "/";
-- Relational functions:
function "=" (X, Y : RATIONAL) return BOOLEAN is
begin
if (X.NUM*Y.DEN = Y.NUM*X.DEN) then
return True;
else
return False;
end if;
end "=";
function NE (X, Y : RATIONAL) return BOOLEAN is
begin
if (X.NUM*Y.DEN = Y.NUM*X.DEN) then
return False;
else
return True;
end if;
end NE; -- not equal
function LT (X, Y : RATIONAL) return BOOLEAN is
R1,R2 : Integer;
begin
R1 := X.NUM*Y.DEN;
R2 := Y.NUM*X.DEN;
if R1 < R2 then
return True;
else
return False;
end if;
end LT; -- less than ( TRUE if X < Y )
function LE (X, Y : RATIONAL) return BOOLEAN is
R1,R2 : Integer;
begin
R1 := X.NUM*Y.DEN;
R2 := Y.NUM*X.DEN;
if R1 <= R2 then
return True;
else
return False;
end if;
end LE; -- less equal ( TRUE if X <= Y )
function GT (X, Y : RATIONAL) return BOOLEAN is
R1,R2 : Integer;
begin
R1 := X.NUM*Y.DEN;
R2 := Y.NUM*X.DEN;
if R1 > R2 then
return True;
else
return False;
end if;
end GT; -- greater than ( TRUE if X > Y )
function GE (X, Y : RATIONAL) return BOOLEAN is
R1,R2 : Integer;
begin
R1 := X.NUM*Y.DEN;
R2 := Y.NUM*X.DEN;
if R1 >= R2 then
return True;
else
return False;
end if;
end GE; -- greater equal ( TRUE if X >= Y )
begin
Put_Line("");
end RATIONALS;
package RATIONALS is
type RATIONAL is private;
RATIONAL_ERROR : exception; -- raised by any subprogram below if denominator = 0
function RAT (N, D : INTEGER) return RATIONAL; -- may raise RATIONAL_ERROR
function NUMER (R : RATIONAL) return INTEGER; -- returns numerator of a rational
function DENOM (R : RATIONAL) return INTEGER; -- returns denominator
procedure GET_IN (R : out RATIONAL); -- inputs rational number from keyboard
procedure PUT_OUT (R : in RATIONAL); -- outputs rational number (normalized) to screen
function NORMAL (R : RATIONAL) return RATIONAL; -- normalizes rational number R
function "+" (X, Y : RATIONAL) return RATIONAL;
function "-" (X, Y : RATIONAL) return RATIONAL;
function "*" (X, Y : RATIONAL) return RATIONAL;
function "/" (X, Y : RATIONAL) return RATIONAL;
function "=" (X, Y : RATIONAL) return BOOLEAN;
function NE (X, Y : RATIONAL) return BOOLEAN; -- not equal
function LT (X, Y : RATIONAL) return BOOLEAN; -- less than ( TRUE if X < Y )
function LE (X, Y : RATIONAL) return BOOLEAN; -- less equal ( TRUE if X <= Y )
function GT (X, Y : RATIONAL) return BOOLEAN; -- greater than ( TRUE if X > Y )
function GE (X, Y : RATIONAL) return BOOLEAN; -- greater equal ( TRUE if X >= Y )
private
type RATIONAL is record
NUM : INTEGER; -- numerator
DEN : INTEGER; -- denominator (cannot be zero! - see exception above)
end record;
end rationals;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment