'============================================================================ ' LINE-EQN.BAS G.H. George, 1998 04 22 ' Determine the equation of a straight line in y = mx + c form, given ' the coordinates of two points on the line (fractions, no decimals). '============================================================================ TYPE Fraction Num AS LONG Den AS LONG END TYPE ' Procedures: ' EnterData: print welcome message; get endpoints (x0, y0), (x1, y1). ' Results: find and print the equation of the line DECLARE SUB EnterData (x0 AS Fraction, y0 AS Fraction, x1 AS Fraction, y1 AS Fraction) DECLARE SUB EnterFraction (Number AS Fraction) DECLARE SUB ReduceFraction (Number AS Fraction) DECLARE FUNCTION NextPrime& (Number AS LONG) DECLARE SUB Results (x0 AS Fraction, x1 AS Fraction, y0 AS Fraction, y1 AS Fraction) DECLARE SUB Subtract (a AS Fraction, b AS Fraction, Diff AS Fraction) ' Global Constants: ' False: logical false (= 0) ' True: logical true (= -1) CONST False = 0, True = NOT False ' Variables: ' x0: x coordinate of one end of the line ' y0: y coordinate of one end of the line ' x1: x coordinate of the other end of the line ' y1: y coordinate of the other end of the line DIM x0 AS Fraction, y0 AS Fraction, x1 AS Fraction, y1 AS Fraction CALL EnterData(x0, y0, x1, y1) CALL Results(x0, y0, x1, y1) END ' Hierarchy chart: ' Main ' | ' | ' --------------------------------------- ' | | ' EnterData Results ' | | ' EnterFraction -------------------| ' | | | ' | | Subtract ' ------ ----------- | ' | | | ' | | ------------------------- ' | | | ' ReduceFraction ' | ' | ' NextPrime& ' ---------- SUB EnterData (x0 AS Fraction, y0 AS Fraction, x1 AS Fraction, y1 AS Fraction) '---------------------------------------------------------------------------- ' Print welcome message; obtain coordinates (x0,y0), (x1, y1) from the user. '---------------------------------------------------------------------------- ' Parameters: ' x0: x coordinate of one end of the line ' y0: y coordinate of one end of the line ' x1: x coordinate of the other end of the line ' y1: y coordinate of the other end of the line ' Procedures ' EnterFraction: ask the user to enter a fraction; reduce it. ' Local Variables: ' SamePoint: logical variable (= true iff the two points are the same) CLS PRINT "The equation of the line joining two points will be found in "; PRINT "fractional form." PRINT PRINT DO PRINT "Enter the x coordinate for one end of the line, "; PRINT "in fractional form: " CALL EnterFraction(x0) PRINT PRINT "Enter the y coordinate for that end of the line, "; PRINT "in fractional form: " CALL EnterFraction(y0) PRINT PRINT "Enter the x coordinate for the other end of the line, "; PRINT "in fractional form: " CALL EnterFraction(x1) PRINT PRINT "Enter the y coordinate for that end of the line, "; PRINT "in fractional form: " CALL EnterFraction(y1) PRINT ' Guard against coincident points: LET SamePoint = (x0.Num = x1.Num AND x0.Den = x1.Den) LET SamePoint = SamePoint AND (y0.Num = y1.Num AND y0.Den = y1.Den) IF SamePoint THEN PRINT "Error: the two points must be distinct! Try again." PRINT END IF LOOP UNTIL NOT SamePoint PRINT END SUB SUB EnterFraction (Number AS Fraction) '============================================================================= ' ** SUBprogram ** (c) 1991, 1998 **>> G.H. George <<** ' - INPUT rational number and reduce it to lowest terms. ' (pasted in from LINSYS.BAS and modified) '============================================================================= ' Procedures: ' ReduceFraction: reduce the user-supplied fraction to lowest terms ' Parameters: ' Number: fraction, reduced to lowest terms ' Local Variables: ' Num: user supplied value for the numerator of the fraction ' Den: user supplied value for the denominator of the fraction DO PRINT " " PRINT CHR$(30); "Numerator of number (INTEGER)"; INPUT Num LOOP UNTIL Num = INT(Num) ' Keep asking until an integer is input. LET Number.Num = Num DO PRINT " " PRINT CHR$(30); "Denominator of number (POSITIVE INTEGER)"; INPUT Den LOOP UNTIL Den = INT(Den) AND Den <> 0 ' Keep asking until input valid. LET Number.Den = Den CALL ReduceFraction(Number) ' Reduce input to lowest terms. END SUB FUNCTION NextPrime& (Number AS LONG) '============================================================================= ' ** User defined FUNCTION ** (c) 1991, 1998 **>> G.H. George <<** ' - given input "Number", find the next prime number. ' Copied and modified from LINSYS.BAS . '============================================================================= ' Procedures: ' ' Parameters: ' Number: incoming number, the next prime above which is to be found ' Local Variables: ' Found: logical variable (= true when nature of candidate is found) ' Cand: candidate next prime number (initially = Number) ' Factor: factor by which to try to divide the candidate prime number ' LastFactor: last factor to try for this candidate prime number DIM Cand AS LONG, Factor AS INTEGER, Found AS LONG LET Cand = Number DO LET Cand = Cand + 1 LET LastFactor = SQR(Cand) LET Factor = 1 LET Found = False DO LET Factor = Factor + 1 IF Factor > LastFactor THEN LET Found = True ' <-- Prime detected. IF Cand MOD Factor = 0 THEN LET Found = True ' <-- "Cand" is composite. LOOP UNTIL Found LOOP UNTIL Factor > LastFactor ' Exit only when prime found. LET NextPrime& = Cand END FUNCTION SUB ReduceFraction (Number AS Fraction) '============================================================================= ' ** SUBprogram ** (c) 1991, 1998 **>> G.H. George <<** ' - cancels the fraction (Number) down to lowest terms. ' (copied and modified from LINSYS.BAS). '============================================================================= ' Procedures: ' NextPrime: returns the next prime number after the argument ' Parameters: ' Number: fraction to be reduced ' Local Variables: ' Proceed: logical variable (= true if further reduction may be needed) ' Prime: prime number; used to test Num& & Den& for common factors DIM Proceed AS INTEGER, Prime AS LONG LET Proceed = True ' no special cases. IF Number.Den = 0 THEN LET Proceed = False ' Avoid zero denominator entirely. ELSE IF Number.Num = 0 THEN ' Check for zero numerator. LET Number.Den = 1 LET Proceed = False ' and no need to reduce further. END IF IF Number.Den < 0 THEN ' Make denominator positive. LET Number.Num = -Number.Num ' - but further reduction may LET Number.Den = -Number.Den ' be needed. END IF IF ABS(Number.Num) = 1 OR Number.Den = 1 THEN LET Proceed = False ' No reduction needed for unit END IF ' numerator or denominator. END IF IF Proceed THEN ' Proceed with main routine ONLY LET Prime = 2 ' when no special cases detected. DO DO IF Number.Num / Prime = INT(Number.Num / Prime) THEN LET Proceed = True ' Test divisibility of numerator. ELSE LET Proceed = False END IF ' IF Number.Den / Prime <> INT(Number.Den / Prime) THEN LET Proceed = False ' Test divisibility of denominator. END IF ' IF Proceed THEN ' Divide out by common factor found. LET Number.Num = Number.Num / Prime LET Number.Den = Number.Den / Prime END IF LOOP WHILE Proceed ' Try same prime again if it's a CF. LET Prime = NextPrime&(Prime) ' else go to next prime number. LOOP UNTIL Prime > ABS(Number.Num) OR Prime > Number.Den ' until lowest terms. END IF END SUB SUB Results (x0 AS Fraction, y0 AS Fraction, x1 AS Fraction, y1 AS Fraction) '---------------------------------------------------------------------------- ' Find and print the equation of the straight line from (x0,y0) to (x1,y1). '---------------------------------------------------------------------------- ' Parameters: ' x0: x coordinate of one end of the line ' y0: y coordinate of one end of the line ' x1: x coordinate of the other end of the line ' y1: y coordinate of the other end of the line ' Procedures: ' Subtract: find and reduce to lowest terms the difference between ' two fractions. ' ReduceFraction: reduce a fraction to its lowest terms ' Local Variables: ' Rise: numerator of m = y1 - y0 ' Runn: denominator of m = x1 - x0 ' m: slope of the line ' mx: product m.x0 ' c: y-axis intercept of the line DIM Rise AS Fraction, Runn AS Fraction, mx AS Fraction DIM m AS Fraction, c AS Fraction CLS PRINT "The equation of the line joining ("; PRINT x0.Num; "/"; x0.Den; ", "; y0.Num; "/"; y0.Den; ") to ("; PRINT x1.Num; "/"; x1.Den; ", "; y1.Num; "/"; y1.Den; ") is" PRINT PRINT IF x0.Num = x1.Num AND x0.Den = x1.Den THEN PRINT "x = "; x0.Num; "/"; x0.Den; ", (which is a vertical line)." PRINT "The slope m and intercept c are UNDEFINED." ELSE CALL Subtract(y1, y0, Rise) ' Find m = (y1-y0) / (x1-x0) CALL Subtract(x1, x0, Runn) LET m.Num = Rise.Num * Runn.Den LET m.Den = Rise.Den * Runn.Num CALL ReduceFraction(m) LET mx.Num = m.Num * x0.Num ' Find c = y0 - m x0 LET mx.Den = m.Den * x0.Den CALL ReduceFraction(mx) CALL Subtract(y0, mx, c) CALL ReduceFraction(c) PRINT " "; USING "###### ######"; m.Num; c.Num PRINT "y = ------ x + ------" PRINT " "; USING "###### ######"; m.Den; c.Den PRINT PRINT "The slope of the line is "; m.Num; "/"; m.Den; "."; IF m.Num = 0 THEN PRINT " (The line is horizontal)." ELSE PRINT END IF PRINT "The y-axis intercept is "; c.Num; "/"; c.Den; "."; IF c.Num = 0 THEN PRINT " (The line passes through the origin)." ELSE PRINT END IF END IF END SUB SUB Subtract (a AS Fraction, b AS Fraction, Diff AS Fraction) '============================================================================= ' Evaluate Diff = a - b as a fraction in its lowest terms. '============================================================================= ' Procedures: ' ReduceFraction: reduce the user-supplied fraction to lowest terms ' Parameters: ' a, b: fractions whose difference is to be found ' Diff: difference a - b as a reduced fraction ' Local Variables: ' LET Diff.Num = a.Num * b.Den - b.Num * a.Den LET Diff.Den = a.Den * b.Den CALL ReduceFraction(Diff) END SUB