Παρασκευή 23 Ιουνίου 2023

Tautology and Contradiction

 We will see here how we can construct truth tables for finding tautology and contradiction. We use here static functions (Called with @ before name) and subs, which are part of same "parent" module, where parent means here a module/function which contains source of child functions/modules. Static functions and sub aren't owner of a scope, but any local variable removed at the exit/return from the call. One reason for anyone to use a static part of code, is the compactness of code.

Modules and normal functions have own scope, and we can call anything we define there, but not something which an inner module define. To use something defined before the call of a module we have to pass it as parameter, or to have it as global. Any local definition hide any global with same name, but if we call an inner module the global one aren't hidden until we define a same name definition.

Identifier True and False are double type values -1 and 0, so here we want to be Boolean. One way to do that is by defining constants. The values after boolean= can be zero or non zero, or False and True (which are the standard True and False, not the new defined).

Especially for global constants we can use a statement like const True, False to check if these constants exist as user's constants (not the predefined True and False). If we place a const bool True =@True which make a local constant then we hide the global one, and this isn't bad, because we have the same result here, but if we need to use a constant value say 1234 which defined globally (until the module which define it exit execution), with a name ABC, a statement ABC=100 make a local variable which hide the global constant, and change the ABC from constant to a variable. So if we use Const ABC without providing a value, interpreter check if there is a global constant ABC and if found one make a reference ABC as local to the global constant, so now a ABC=100 will raise error, because ABC exist as  local constant. If nothing found, at Const ABC statement, interpreter raise error, for missing constant.

In M2000 not all inner modules defined on same source as the parent. We can load modules from disk using Load statement on any module or function.  Interpreter use a cashed list of functions depending on loading modules, and we can exclude cash list using properly the load function.


Module CanonicalForms2 {
Font "Verdana"
linespace 0
form 60
global const True as boolean=True, False as boolean=False
module tautology {
const True, False
print part "  tautology based on truth table: P ∨ ¬P"
print Under $(7),"P", "¬P", "P ∨ ¬P"
print under
P = (True, False)
Q = (True, False)
eP = Each(P)
boolean acc=true
While eP
acc = acc and @P() or not @P()
print @P(), not @P(), @P() or not @P()
end While
tautology(acc)
print
print part "  tautology based on truth table: P → (Q → P)"
print Under $(7),"Q", "P", "Q → P", "P → (Q → P)"
print Under
acc = True
eP = Each(P)
While eP
eQ=Each(Q)
While eQ
acc = acc and @implication(@P(), @implication(@Q(),@P()))
print @Q(), @P(), @implication(@Q(),@P()), @implication(@P(), @implication(@Q(),@P()))
end While
end While
tautology(acc)
print
}
module contradiction {
const True, False
print part "  contradiction based on truth table: P ∧ ¬P"
print Under $(7),"P", "¬P", "P ∧ ¬P"
print under
P = (True, False)
Q = (True, False)
eP = Each(P)
boolean acc=false
While eP
acc = acc or @P() and not @P()
print @P(), not @P(), @P() and not @P()
end While
contradiction(acc)
print
print
print part " contradiction based on truth table: ¬(P ∨ ¬(P ∧ Q))"
print Under $(7),"P", "Q", "P ∧ Q","¬(P ∧ Q)", "P ∨ ¬(P ∧ Q)","¬(P ∨ ¬(P ∧ Q))"
print Under
acc = false
eP = Each(P)
While eP
eQ=Each(Q)
While eQ
acc = acc and not (@P() or not (@P() and @Q()))
print @P(), @Q(), @P() and @Q(), not (@P() and @Q()),
print @P() or not (@P() and @Q()), not (@P() or not (@P() and @Q()))
end While
end While
contradiction(acc)
}
module check_for_contradiction_or_tautology {
const True, False
print
print part "  check for contradiction and tautology: (P → Q)→ P"
print Under $(7),"P", "Q", "P → Q", "(P → Q)→ P"
print under
P = (True, False)
Q = (True, False)
eP = Each(P)
boolean acc1=true, acc2=false, res
While eP
eQ=Each(Q)
While eQ
res = @implication(@implication(@P(),@Q()),@P())
acc1 = acc1 and res
acc2 = acc2 or res
print @P(), @Q(), @implication(@P(),@Q()), res
end While
end While
tautology(acc1)
contradiction(acc2)
}
tautology
contradiction
check_for_contradiction_or_tautology
push key$
drop
// inner modules can found static functions on the parent, which are in the same code
// but variables scope isn't extend to parent.
// So eP and eQ must defined prior to call  these functions
function implication(P as boolean, Q as boolean)
// canonical form
=Not P Or Q
end function
function P()
=array(eP)
end function
function Q()
=array(eQ)
end function
sub tautology(acc as boolean)
if acc then
print "we have tautology, all True"
else
print "we haven't tautology, not all True"
end if
end sub
sub contradiction(acc as boolean)
if not acc then
print "we have contradiction, all False"
else
print "we haven't contradiction, not all False"
end if
end sub
}
CanonicalForms2

Τρίτη 6 Ιουνίου 2023

Canonical Forms for Logical implication and equivalence (new)

We see here how and why we use two types of functions, plus the object of the example to print truth tables for some functions.

Here we make a program for displaying  truth tables for two functions the implication and equivalence. Because True and False are of type Double (-1 and 0), we make them as Boolean types, so at the Print statement we get True and False (right justified as numbers). All comparisons and logical expressions return  result as Boolean type. A non zero number converted to True so 15 and 3 return True, but binary.and(15, 3) return 3.

We use two types of functions, normal functions like implication() and equivalence() and simple functions P() and Q() which have to call as @P() and @Q(). Simple functions use module scope, so eP and eQ can be used. Normal functions have own scope. The True as Boolean can be used inside implication (but here we didn't use it), because we declare it as Global (for the lifetime of module CanonicalForm1, and from the line we defined it). Modules and Functions which called them with normal call can't be see anything out of them, and anything inside other modules/functions which we define in these modules/functions. Normal functions can call themselves. Simple functions can call anything defined in module as far, and always simple functions. When we first time call a simple function a search begin from the end to start until interpreter found it, and then register to a fast call list, for the next time we call it again. Normal functions works different. The function's code loaded in a list with a key to the specific defined identifier, using a hash table. So we can reload another function code if we wish. Also normal functions can be passed by reference, but simple functions can't. A lambda function is a normal function with a list of closures, where these closures are every time in scope with code of lambda and any recursive call (we use Lambda() to call the current function). Simple functions can use recursion, using the defined name of current simple function.

Other difference between simple functions and other (normal/lambda): 

  • A simple function can't be called like a module using Call statement, but only in expressions. 
  • We have to use Local to define variables and arrays for local use on simple functions. All other have own scope, so anything defined by default is local.
  • Stack of values (used also for passing parameters) are the same as the module's stack of values for simple functions so we can't easy use variadic call for functions. Normal and Lambda functions when we call them in expressions we pass a new stack of values with any parameter value on it, and only for the specific call (the stack erased at the exit). At recursion simple functions still use the same stack of values, but normal and lambda function use a new one for every call.
  • We can't pass by reference an array item or a static variable to a simple function. We can do this for normal and lambda functions.
An example about passing array item and static variable to a normal function:
Module TestByRef {
Dim a(10)=3
Static Z=100
Function k(&m) {
=m
m++
}
Print a(3)
Print k(&a(3))
Print a(3)
Print Z
Print k(&Z)
Print Z
}
TestByRef
TestByRef
Clear  // clear variables, no functions/modules
TestByRef
And this is an example using simple function (the m in function k() is local by default):

Module TestByRef1 {
m=10
Print m
Print @k(&m)
Print m
Function k(&m)
=m
m++
End Function


}
TestByRef1


The final example. This program use Unicode symbols from here

Module CanonicalForms1 {
Font "Verdana"
Mode 15.5 // 15.5 pt size current font
// make True and False as boolean values
Global Boolean True=@True, False=@False
Function implication(P as boolean, Q as boolean) {
// canonical form
=Not P Or Q
}
Function equivalence(P as boolean, Q as boolean) {
//canonical form
=(Not P Or Q) And (Not Q Or P)
}
Print part "  implication truth table: (P → Q) ⇒ ¬P ∨ Q"
Print Under $(7),"P", "Q", "(P → Q)"
Print under
P=(True, False)
Q=(True, False)
eP=Each(P)
While eP
eQ=Each(Q)
While eQ
Print @P(), @Q(), implication(@P(),@Q())
End While
End While
Print
Print part "  equivalence truth table: (P ↔ Q) ⇔ (P → Q) ∧ (Q → P)"
Print Under $(7),"P", "Q", "(P ↔ Q)"
Print under
eP=Each(P)
While eP
eQ=Each(Q)
While eQ
Print @P(), @Q(), equivalence(@P(),@Q())
End While
End While

Print
Print part "  logical AND truth table: P ∧ Q"
Print Under $(7),"P", "Q", "(P ∧ Q)"
Print under
eP=Each(P)
While eP
eQ=Each(Q)
While eQ
Print @P(), @Q(), @P() and @Q()
End While
End While

Print
Print part "  logical OR truth table: P ∨ Q"
Print Under $(7),"P", "Q", "(P ∨ Q)"
Print under
eP=Each(P)
While eP
eQ=Each(Q)
While eQ
Print @P(), @Q(), @P() or @Q()
End While
End While

Print
Print part "  logical NOT truth table: ¬P"
Print Under $(7),"P","", "(¬P)"
Print under
eP=Each(P)
While eP
Print @P(), "", not @P()
End While

Function P()
=array(eP)
End Function
Function Q()
=array(eQ)
End Function
}
CanonicalForms1

Παρασκευή 2 Ιουνίου 2023

Find set of Differences from two sets of type item

 This is a simple program, which use a type item as enum type, and lists as automatic arrays (tuple). Also we use the current stack of values and the formula array([]) which leave an empty stack of values, and return an array of item converting the stack object to array object. The [] identifier return the stack of values, while leave an empty stack (So we didn't get a pointer to current stack of values, that not allowed from interpreter). The array() functions if get a stack pointer make a new tuple and move all elements from stack object to array object

Look this sample code. Variable k is of type mStiva, use Type$(k) to get the name. Length of k is 3, the we make L as array(k) so length of L is 3 but length of k is 0. To preserve items on k we have to use L=array(stack(k)). Function stack() return a new stack object.

k=stack:=1,2,3
Print Len(k)=3
L=array(k)
Print Len(k)=0
Print Len(L)=3

We can produce a stack item from an array (a tuple), but without reducing items on that array. Always we get shallow copies, so if we have pointers to arrays, these are just copies of these pointers not the arrays as is.

m=stack(L)
Print type$(m)="mStiva"
Print Len(L)=3
Print Len(M)=3


The program:


Module TestDiff {
// Find differnences of two set of items of type item
Enum item {
pig=random(-20, 1000), cat, dog, cow, elephant, mice, horse
}

ListA=(pig, cow, elephant, mice)
ListB=(dog, cat, pig, mice)

k=min.data(len(ListA), len(ListB))
if len(ListB)=k then M1=ListA : M2=ListB else M2=ListA:M1=ListB
M=each(M1)
flush
integer nullitem=pig-1
dim a(pig to horse)=nullitem

While M
i=array(M)
a(i)=i
End While
M=each(M2)
While M
i=array(M)
if a(i)=i then a(i)=nullitem else a(i)=i
End While
M=each(a())
flush
While M
if array(m)>0 then push array(M)
End While
Pen 15 {
dispnames(ListA, "ListA")
dispnames(ListB, "ListB")
}

if empty then
print "no differences found"
else
M3=Array([])
Pen 11 {
dispnames(M3,"Differences")
}
End if
Sub dispnames(k as array, title$)
Local M=each(k)
Stack new {
While M
Data eval$(array(M))
End While
print title$;": ";array([])#str$(", ")
}
End Sub
}
TestDiff


Παρασκευή 26 Μαΐου 2023

Convert BASIC to M2000 (Astronomy)

 

From BASIC PROGRAMS FROM SKY & TELESCOPE  we can convert some programs to M2000

Original program: ROCKET.BAS

We have to make a simple Print_Using statement for one parameter V displayed with the format in A$. Also we have to make LOG(), SQR(), EXP() and STRING$() to be same as BASIC. LOG() in M2000 return decimal logarithm, and LN() return natural logarithm.

Also at INPUT statement, M2000 never use ? if we use a string label so we can use ? and a space at each input label (here we have only one).

MODULE PRINT_USING (A$, V) {
B$=LEFTPART$(A$,"#")
C$=STRREV$(LEFTPART$(STRREV$(A$),"#"))
D$=MID$(A$, LEN(B$)+1, LEN(A$)-LEN(B$)-LEN(C$))
D1=LEN(RIGHTPART$(D$,"."))
D2=-LEN(D$)
PRINT FORMAT$(B$+"{0:"+D1+":"+D2+"}"+C$, V)
}
DEF LOG(X)=LN(X)
DEF SQR(x)=SQRT(x)
DEF EXP(x)=2.7182818284**x
DEF STRING$(A,B$)=@STRING$(B$,A)
10 REPORT "ROCKET.BAS by Brian Tung"
20 REPORT "ADAPTED FOR M2000"
30 REM
40 A=1.032: REM Earth gravity in light-years per year squared
50 INPUT "Distance in light-years (0-100 million)? "; D
60 IF D>=0 AND D<=100000000 THEN 80
70 PRINT "Distance must be between 0 and 100 million l-y": GOTO 50
80 D1=D/2
90 T=SQR(D1*D1+(2*D1/A))
100 X=A*T
110 M=1: REM Lines 110-180 compute inverse sinh
120 IF X<0 THEN M=-1
130 S=LOG(ABS(X)+1)
140 S1=S+1
150 X1=(EXP(S)-EXP(-S))/2-ABS(X)
160 S1=X1/(EXP(S)+EXP(-S))/2
170 S=S-S1
180 IF ABS(S1)>.0000001 THEN 150
190 T1=1/A*S*M
200 V=A*T/SQR(1+(A*T)*(A*T))
210 PRINT_USING "Time on Earth: #########.### years", 2*T
220 PRINT_USING "Time on board: #########.### years", 2*T1
230 Z$ = "Top speed: #.###"
240 IF D<1 THEN 280
250 Z1=INT(2*LOG(D)/LOG(10))
260 IF D>=1 AND D<10000000 THEN Z$=Z$+STRING$(Z1, "#")
270 IF D>=10000000 THEN Z$=Z$+"#############"
280 Z$=Z$+" c"
290 PRINT_USING Z$, V
300 END
900 REM ---------------------------
910 REM APPEARED IN COMPUTERS IN
920 REM ASTRONOMY, SKY & TELESCOPE,
930 REM FEBRUARY 2002, PAGE 66
940 REM ---------------------------

Another program is the LOOKBAK2.BAS

Because this program use wide display (80 characters at least) we can make console to use a 80X32 display, full screen. Also it is best to use Courier New font for editor/screen.

Also except for PRINT_USING, LOG() and SQR() was another problem. The original program use IF expr GOTO number statement, so the GOTO change to THEN. M2000 can use IF expr THEN GOTO numeric/alphanumeric label, or IF expr THEN numeric label. Also numeric labels can be from 0 to 99999 (5 digits max), but alphanumeric can be any size. We can use 010 for numeric labels (leading zeros). Also the order isn't mandatory, we may have 1000 previous of 500.


When we have to input a number like .35 we have to place like this 0.35 because the input statement in M2000 need sign or number as first character for numeric input. Numeric input always use the LOCALE sign for decimal point, and we have to use keyboard "." and we see comma for locale 1032 and dot for locale 1033. If we input more than one value, like Input A, B, C we can use keyboard comma as enter to enter next value, or just enter, in any case se will see a comma and a space and then the new input begin.

// we define A as string, so we have string input
String A: Input "number? ", A: Print A
Clear  // clear variables
// this is a numeric Input because A not exist and defined as Double type
Input "number? ", A: Print A
// A$ is string by default
Input "string? ",A$: Print A$
Clear
// using variant type
Variant A="ok"
Input "string? ", A: Print A, Type$(A)
A=100 // Variant can change type on assign
Input "number? ", A: Print A, Type$(A)



This is the program with the M2000 code

MODULE PRINT_USING (A$, V) {
B$=LEFTPART$(A$,"#")
C$=STRREV$(LEFTPART$(STRREV$(A$),"#"))
D$=MID$(A$, LEN(B$)+1, LEN(A$)-LEN(B$)-LEN(C$))
D1=LEN(RIGHTPART$(D$,"."))
D2=-LEN(D$)
PRINT FORMAT$(B$+"{0:"+D1+":"+D2+"}"+C$, V)
}
DEF LOG(X)=LN(X)
DEF SQR(x)=SQRT(x)
FONT "COURIER NEW"
FORM 80, 32
ITALIC 1
REPORT 2, {LOOKBAK2.BAS - May 2001; Updated Sept. 2003}
ITALIC 0
REPORT {APPEARED IN COMPUTERS IN ASTRONOMY,
SKY & TELESCOPE, AUGUST 2001, PAGE 62.
Corrections made Sept. 2003 to lines 232, 550, and 630, with
many thanks to Bruce Nelson, a great mathematician whose hobby
is cosmology and who decided to re-derive all these equations!
The updates give smoother results when OMC is small and more
accurate results for HT and ST for very large values of Z.


}
100 REM LOOKBAK2.BAS - May 2001; Updated Sept. 2003
110 REM by Thomas A. Weil, taweil@aol.com
112 REM Now handles user-specified values for both OmegaM and OmegaL.
114 REM Includes some code from Ned Wright's Cosmology Calculator,
116 REM http://www.astro.ucla.edu/~wright/CosmoCalc.html
120 INPUT "Enter Matter Density of the universe, OmegaM (0 - 2.0):"; OMG
130 IF OMG<0 OR OMG>2 THEN 120
140 INPUT "Enter Cosmological Constant, OmegaL (0. - 1.0):"; LAM
150 IF LAM<0 OR LAM>1 THEN 140
160 INPUT "Will you enter (A)ge of the universe or (H)ubble constant:"; AH$
170 IF AH$="H" OR AH$="h" THEN 210
180 IF AH$<>"A" AND AH$<>"a" THEN 160
190 INPUT "Enter Age of the universe NOW in billions of years:"; TN
200 TN=TN*1E+09 : HN=60 : M=8 : GOTO 220
210 INPUT "Enter Hubble constant in km/sec/Mpc:"; HN : M=1
212 REM N is the number of iterations to be used in each FOR-NEXT.
214 REM Ned Wright's Cosmology Calculator uses N=1000, but N=200
216 REM is faster and still seems to be quite accurate.
218 REM HFAC converts the Hubble constant to units of km/sec/Mpc from speed
219 REM as a fraction of the speed of light per light year of distance.
220 N=200 : DELTA=.0000001 : HFAC=9.7782E+11 : E=2.718282 : PARSEC=3.2616
222 REM For user-specified TN, we now calculate HN, but since ORD depends
224 REM on HN, we need to iterate AgeFac until the results converge.
226 REM AgeFac is the factor to multiply the inverse of the Hubble
228 REM constant by to determine the age of the universe.
230 FOR J=1 TO M
232 REM OMC is Omega(Curvature); OMC=0 gives us a "flat" universe.
234 REM ORD is Omega(Radiation), which is radiation pressure, which was a
236 REM major contributor to expansion when the universe was very young.
240 ORD=.4165/(HN*HN) : OMC=1-OMG-LAM-ORD : Z=5 : AZ=1/(1+Z) : AA=0
242 REM Calc. age at redshift Z, and lookback time, and add them to get Age
244 REM Now (TN). For this calculation we assume Z=5, but any value would do.
250 TRS=0 : TLB=0 : FOR I=1 TO N : A=AZ*(I-.5)/N : AA=AZ+(1-AZ)*(I-.5)/N
260 TRS=TRS+1/SQR(OMC+(OMG/A)+(ORD/(A*A))+(LAM*A*A))
270 TLB=TLB+1/SQR(OMC+(OMG/AA)+(ORD/(AA*AA))+(LAM*AA*AA)) : NEXT I
280 AGEFAC=TLB/N*(1-AZ)+TRS/N*AZ
290 IF AH$="H" OR AH$="h" THEN 310
300 HN=AGEFAC/TN*HFAC
310 NEXT J
320 TN=AGEFAC/HN*HFAC
330 INPUT "Will you enter (T)ime THEN or (R)edshift of the light we see NOW:"; TR$
340 IF TR$="R" OR TR$="r" THEN 470
350 IF TR$<>"T" AND TR$<>"t" THEN 330
360 INPUT "Enter Age of the universe THEN, in billions of years:"; TTT
370 TTT=TTT*1E+09 : IF TTT>299999 THEN 410
380 PRINT
390 PRINT " You cannot see back to a time earlier than about 300,000 years"
392 REM My first article in S&T, Sept. 1997, page 59, explains why.
400 PRINT : GOTO 330
410 PRINT " Finding what redshift matches Age THEN ......" : Z=(TN-TTT)/TN
420 AZ=1/(1+Z) : TRS=0 : FOR I=1 TO N : A=AZ*(I-.5)/N
430 TRS=TRS+1/SQR(OMC+OMG/A+ORD/(A*A)+LAM*A*A) : NEXT I
440 TT=TRS/N*HFAC/HN*AZ : TOL=TOL+DELTA
450 IF TT/TTT>1-TOL AND TT/TTT<1+TOL THEN 480
452 REM If Time Then (TT) doesn't match yet, adjust Z accordingly
460 Z=Z*(.2+.8*TT/TTT) : GOTO 420
470 INPUT "Enter redshift value for the light we see NOW:"; Z
472 REM Calculate Distances
480 DCMR=0 : AZ=1/(1+Z) : FOR I=1 TO N
490 A=AZ+(1-AZ)*(I-.5)/N : ADOT=SQR(OMC+(OMG/A)+(ORD/(A*A))+(LAM*A*A))
500 DCMR=DCMR+1/(A*ADOT) : NEXT I
510 DCMR=(1-AZ)*DCMR/N : X=SQR(ABS(OMC))*DCMR : IF X<=.1 THEN 550
520 IF OMC>0 THEN 540
530 RATIO=SIN(X)/X : GOTO 580
540 RATIO=.5*(E^X-E^(-X))/X : GOTO 580
550 Y=X*X : IF OMC>=0 THEN 570
560 Y=(-Y)
570 RATIO=1+Y/6+Y*Y/120
580 DL=AZ*RATIO*DCMR/(AZ*AZ)*977.82/HN : DN=DL/(1+Z) : DT=DN/(1+Z)
582 REM Calculate Time Then (TT) at redshift Z
590 AZ=1/(1+Z) : AGE=0 : FOR I=1 TO N
600 A=AZ*(I-.5)/N : AGE=AGE+1/SQR(OMC+OMG/A+ORD/(A*A)+LAM*A*A) : NEXT I
610 TT=HFAC/HN*AZ*AGE/N : TV=TN-TT : DMOD=5*.4343*LOG(DL*1E+09/(10*PARSEC))
620 IF TT<300000 THEN 380
630 HT=HN*SQR(OMG*(1+Z)^3+(1-OMG-LAM-ORD)*(1+Z)^2+LAM+ORD*(1+Z)^4)
640 ST=HT*DT/977.82 : SC=Z+1 : SN=HN*DN*1E+09/HFAC
650 PRINT_USING "Age Factor NOW  (Age=Fac/H0) = ##.####",AGEFAC
660 PRINT_USING "Age of the universe NOW  =####.#### billion years", TN/1E+09
670 PRINT_USING "Age of the universe THEN =####.#### billion years", TT/1E+09
680 PRINT_USING "Light travel time        =####.#### billion years", TV/1E+09
690 PRINT_USING "Redshift of the light we see NOW      =#####.###", Z
700 PRINT_USING "Scale of the universe NOW versus THEN =#####.###", SC
710 PRINT_USING "Distance of object THEN =  #####.### billion light-years", DT
720 PRINT_USING "Distance of object NOW  = ######.### billion light-years", DN
730 PRINT_USING "Luminosity Distance NOW =#######.### billion light-years", DL
740 PRINT_USING "Distance Modulus     = ######.###", DMOD
750 PRINT_USING "Speed away from us THEN =####.### x speed of light*", ST
760 PRINT_USING "Speed away from us NOW  =####.### x speed of light*", SN
770 PRINT_USING "Hubble constant THEN   =########.## km/sec/megaparsec", HT
780 PRINT_USING "Hubble constant NOW    =########.## km/sec/megaparsec", HN
790 PRINT " * Not the object's own speed, but caused by the expansion of space."
800 END
900 REM ---------------------------
910 REM APPEARED IN COMPUTERS IN ASTRONOMY,
920 REM SKY & TELESCOPE, AUGUST 2001, PAGE 62.
930 REM Corrections made Sept. 2003 to lines 232, 550, and 630, with
932 REM many thanks to Bruce Nelson, a great mathematician whose hobby
934 REM is cosmology and who decided to re-derive all these equations!
936 REM The updates give smoother results when OMC is small and more
938 REM accurate results for HT and ST for very large values of Z.
940 REM ---------------------------
950 REM ** SAMPLE RUN, for OmegaM=.35, OmegaL=.65, H0=61, and Z=1.7 **
960 REM Enter Matter Density of the Universe, OmegaM (0 - 2.0)? .35
970 REM Enter Cosmological Constant, OmegaL (0. - 1.0)? .65
980 REM Will you enter (A)ge of the universe or (H)ubble constant? H
990 REM Enter Hubble constant in km/sec/Mpc? 61
1000 REM Will you enter (T)ime THEN or (R)edshift of the light we see NOW? R
1010 REM Enter redshift value for the light we see NOW? 1.7
1020 REM Age Factor NOW (Age=Fac/H0) = 0.9226
1030 REM Age of the universe NOW = 14.7887 billion years
1040 REM Age of the universe THEN = 4.0054 billion years
1050 REM Light travel time = 10.7833 billion years
1060 REM Redshift of the light we see NOW = 1.700
1070 REM Scale of the universe NOW versus THEN = 2.700
1080 REM Distance of object THEN = 6.292 billion light-years
1090 REM Distance of object NOW = 16.987 billion light-years
1100 REM Luminosity Distance NOW = 45.865 billion light-years
1110 REM Distance Modulus = 45.741
1120 REM Speed away from us THEN = 1.078 x speed of light*
1130 REM Speed away from us NOW = 1.060 x speed of light*
1140 REM Hubble constant THEN = 167.55 km/sec/megaparsec
1150 REM Hubble constant NOW = 61.00 km/sec/megaparsec
1160 REM * Not the object's own speed, but caused by the expansion of space.


Last is the PRINT_USING statement for multiple numeric values:

The PRINT_USING module get these "A=#####.##ms B=##.##sec c=###%", 1, 1.3, 12.4 and execute a compiled code (through INLINE statement), identical to:

PRINT FORMAT$("A={0:2:-8}ms B={1:2:-5}sec c={2:0:-3}%",1, 1.3, 12.4)

but instead to convert numeric to string and then convert back to  number, we change the parameter list with NUMBER for each numeric parameter. 

PRINT FORMAT$("A={0:2:-8}ms B={1:2:-5}sec c={2:0:-3}%",NUMBER, NUMBER,  NUMBER)

The NUMBER identifier used to pop a number from stack of values. So when we call PRINT_USING we get the string value by a READ A$ statement (which place automatic from Interpreter) and then leave other values on stack for getting them later by using NUMBER. When we finish with INLINE statement we perform a FLUSH statement which make stack empty. So if we place more values which the format string can't process, then these erased. If we place less then a Number find empty stack and this raise error.  If we place a string in place of a number we get error too.

Format$() convert decimal point based on LOCALE, so LOCALE 1032 use comma, and LOCALE 1033 use dot. For source always decimal point is dot.


MODULE PRINT_USING (A$) {
DEF P,B$,B1$,C$
REPEAT
B1$=LEFTPART$(A$,"#")+"{"+P
B$+=B1$
A$=MID$(A$,LEN(B1$))
INTEGER D2=0, D1=0, I=1
WHILE MID$(A$,I,1)="#"
I++
END WHILE
D2=I
IF MID$(A$,I,1)="." THEN
D2++:I++
D1=0
WHILE MID$(A$,I,1)="#"
D1++
I++
END WHILE
D2+=D1
END IF
A$=MID$(A$,D2)
C$=LEFTPART$(A$,"#")
IF LEN(C$)=0 THEN C$=A$:A$=""
B$+=":"+D1+":-"+D2+"}"
P++
WHEN A$<>""
TRY OK {
INLINE "PRINT FORMAT$("+QUOTE$(B$+C$)+STRING$(", NUMBER", P)+")"
}
IF ERROR OR NOT OK THEN C$=ERROR$: ERROR "PROBLEM ON PARAMETERS"
FLUSH // DELETE MORE VALUES
}
PRINT_USING "A=#####.##ms B=##.##sec c=###%", 1, 1.3, 12.4
PRINT FORMAT$("A={0:2:-8}ms B={1:2:-5}sec c={2:0:-3}%",1, 1.3, 12.4)