Jump to content

M2000 Interpreter rational numbers

From Rosetta Code

M2000 Interpreter

Module RationalNumbers {
	Class Rational {
		numerator as decimal, denominator as decimal
		gcd=lambda->0
		lcm=lambda->0
		operator "+" {
			Read l
			denom=.lcm(l.denominator, .denominator)
			.numerator<=denom/l.denominator*l.numerator+denom/.denominator*.numerator
			if .numerator==0 then denom=1
			.denominator<=denom
		}
		Operator Unary {
			.numerator-!
		}
		Operator "-" {
			Read l
			Call Operator "+", -l
		}
		Operator high "*" {
			Read l
			g1=.gcd(l.numerator,.denominator)
			g2=.gcd(.numerator, l.denominator)
			Push l.numerator/g1*.numerator/g2
			Push l.denominator/g2*.denominator/g1
			Read .denominator, .numerator
		}
		Function Inverse {
			if .numerator==0 then Error "Division by zero"
			ret=This
			sign=Sgn(ret.numerator) : if sign<0 then ret.numerator-!
			swap ret.numerator, ret.denominator
			if sign<0 then ret.numerator-!
			=ret
		}
		Operator high"/" {
			Read l
			call operator "*", l.inverse()
		}
		Function Power {
			Read pow as long
			ret=This
			ret.numerator<=.numerator^pow
			ret.denominator<=.denominator^pow
			=ret
		}
		Operator "=" {
			Read l
			Boolean T=True, F=False
			if Abs(Sgn(l.numerator))+Abs(Sgn(.numerator))=0 then Push T: exit
			if Sgn(l.numerator) <>Sgn(.numerator) then Push F : exit
			pcomp=l/this
			Push pcomp.numerator=1 and pcomp.denominator=1
		}
		Operator  ">" {
			Read l
			Boolean F
			if Abs(Sgn(l.numerator))+Abs(Sgn(.numerator))=0 then Push F: exit
			if Sgn(l.numerator)=0 then {
				Push .numerator>0
			} Else {
				pcomp=this/l
				Push pcomp.real>1
			}
		}
		Operator ">=" {
			Read l
			if Sgn(l.numerator)=0 then {
				Push .numerator>=0
			} Else {
				pcomp=this/l
				Push pcomp.real>=1
			}
		}      
		Operator "<" {
			Read l
			Boolean F
			if Abs(Sgn(l.numerator))+Abs(Sgn(.numerator))=0 then Push F: exit
			if Sgn(l.numerator)=0 then {
				Push .numerator<0
			} Else {
				pcomp=this/l
				Push pcomp.real<1
			}
		}
		Operator "<=" {
			Read l
			if Sgn(l.numerator)=0 then {
				Push .numerator<=0
			} Else {
				pcomp=this/l
				Push pcomp.real<=1
			}            
		}
		Operator "<>" {
			Read l
			if Sgn(l.numerator)=0 then {
				Push .numerator<>0
			} Else {
				pcomp=this/l
				Push pcomp.real<>1
			}            
		}
		Group Real {
			value {
				link parent numerator, denominator to n, d
				=n/d
			}
		}
		Group ToString$ {
			value {
				link parent numerator, denominator to n, d
				=Str$(n)+"/"+Str$(d,"")
			}      
		}
	class:
		Module Rational (.numerator, .denominator) {
			if .denominator=0 then .denominator<=1
			while frac(.numerator)<>0 {
				.numerator*=10@
				.denominator*=10@
			}
			sgn=Sgn(.numerator)*Sgn(.denominator)
			.denominator<=abs(.denominator)
			.numerator<=abs(.numerator)*sgn
			gcd1=lambda (a as decimal, b as decimal) -> {
				if a<b then swap a,b
				g=a mod b
				while g {
					a=b:b=g: g=a mod b
				}
				=abs(b)
			}
			gdcval=gcd1(abs(.numerator), .denominator)
			if gdcval<.denominator and gdcval<>0 then
				.denominator/=gdcval
				.numerator/=gdcval
			end if
			.gcd<=gcd1
			.lcm<=lambda gcd=gcd1 (a as decimal, b as decimal) -> {
			=a/gcd(a,b)*b
			}
		}
	}
	Print rational(-3,3)<>rational(-3,3)  ' false
	M=Rational(10, 150)
	N=Rational(2, 4)
	Print "M.real+N.real=";M.real+N.real
	Print "Z=M+N"
	Z=M+N
	Print 10/150@+2/4@
	Print "Z.real="; Z.real
	Print "(";M.numerator;"/"; M.denominator;") + (";N.numerator;"/"; N.denominator;") = (";Z.numerator;"/";Z.denominator;")"
	Print M.tostring$+ " +"+N.tostring$+" ="+Z.tostring$
	Print -10/150@+2/4@
	Z=-M+N
	Print "-"+M.tostring$+ " +"+N.tostring$+" ="+Z.tostring$
	Print Z.numerator, Z.denominator, Z.numerator/Z.denominator
	Print -10/150@+2/4@
	Print Z.real
	Z=M-N
	Print Z.numerator, Z.denominator
	Print 10/150@-2/4@
	Print Z.real
	Z=M*N
	Print Z.numerator, Z.denominator
	Print (10/150@)*(2/4@)
	Print Z.real
	Z=M/N
	Print Z.numerator, Z.denominator
	Print (10/150@)/(2/4@)
	Print z.tostring$
	Print Z.real
	Print "Z power 2 = ";
	
	Z=Z.Power(2)
	Print Z.real
	Print z.tostring$;" = ";eval(z.tostring$)   
	Print Z=Z
	Print Z=N, "            SHOULD BE FALSE"  ' false
	Print Z=-Z , "            SHOULD BE FALSE"  ' false
	ZZ=-Z
	Print ZZ=ZZ
	Print -Z=-Z
	Print Z.numerator, Z.denominator
	Print Z.real, Z.tostring$
	\\ Array of rational numbers
	Dim K(100)=rational(1,1)
	M=K(4)+K(3)
	Print M.real
	Print K(4).toString$
	
	pk->(Z)
	Print pk=>toString$+" +"
	zzz=k(4)+pk
	Print zzz.toString$+ " ="+K(4).toString$+" +"+pk=>toString$
	
	zzz=Rational(10,1)+Rational(3,1)*Rational(2,1)
	Print zzz.toString$, zzz.real=16
	zzz=Rational(10,1)*Rational(3,1)+Rational(2,1)
	Print zzz.toString$, zzz.real=32
}
RationalNumbers
Cookies help us deliver our services. By using our services, you agree to our use of cookies.