Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Writing and Calling the Factorial Function (QBasic rookie) 1

Status
Not open for further replies.

Argonath

Technical User
Feb 1, 2004
10
US
I am relatively new to QBasic and am writing a simple tool which will compute (and display) the results of the Binomial PDF and CDF given n trials, k opportunities, and a probability of success in each trial of ReplyProb.

I need to use a Factorial function but since QBasic has no such function I attempted to write a subroutine to do my own and am still getting an "Operator Overload" message.

Any help would be most appreciated[glasses]

What the code is supposed to do:
------------------------------------------------------------
Print out the PDF and CDF of the discrete Binomial distribution for K successes out of N trials with the probability of success of each trial = ReplyProb

The code is as follows:
----------------------------------------------------------------------------------------------------------------------

DECLARE SUB simpfact (in AS INTEGER)
DIM SHARED N AS INTEGER
DIM SHARED K AS INTEGER
DIM SHARED i AS INTEGER
PRINT ("Input Reply Probability");
INPUT ReplyProb
PRINT ("Input Reply Threshold")
INPUT K
PRINT ("Input Sliding Window Length");
INPUT N
CALL simpfact(N)
a = total
FOR i = K TO N
CALL simpfact(i)
b(i) = total
CALL simpfact(N - i)
c(i) = total
BinomialSum = a / (b(i) * c(i)) * ReplyProb ^ i * ReplyProb ^ (N - i)
tot(i) = tot(i) + BinomialSum
PRINT ("Binomial Sum Iterator"); BinomialSum
PRINT ("Cumulative Binomial Sum="); tot(i)
PRINT ("")
NEXT i
END

------------------------------------------------------------
------------------------------------------------------------

What the subroutine should do:
------------------------------------------------------------
(1) Call the subroutine simpfact with parameter N
(2) Since in is not equal to 1 (say, N=9), b=in=9, total = total * b = 9; if N = in = 1, then total=1 and the value returned to total after the function call is 1
(3) compute b as (9-1), (9-2), ... , (9-9) and total = total * 9 * (9-1) * (9-2) * ...
(4) return the value of total to the line immediately after the function call
------------------------------------------------------------

The subroutine is as follows:
------------------------------------------------------------------------------------------------------------------------
SUB simpfact (in AS INTEGER) STATIC
total=1
FOR i = 0 TO in
IF (in = 1) THEN
total = 1
ELSE
b = (in - i)
total = total * b
END IF
NEXT i
END SUB

------------------------------------------------------------


 
Since you didn't declared Total as shared, it will always be 0.
Hence the errors.
I suggest you better write the function for factorial, so you just write like this:
b(i)=simpfact(i)

Another thing is to watch for overflow: factorial grous huge pretty fast... Declaring
DEF DBL A-Z
in the first line makes all variables bouble by defalult (up to 10^307 instead of 10^37 without this line).
 
The easiest way to use factorials is to make an array of them and load them. I would use strings rather than variables, the largest variable qbasic offers will only go to 7! without overflowing.

copy this into a text file

0,1,2,6,24,120,720,5760,51840,518400,5702400,68428800
889574400,12454041600,186810624000

^^the first 15 factorial figures^^
then use this code to load it.

DIM SHARED factorial$(15)
OPEN "file.txt" FOR INPUT AS #1
FOR a% = 0 TO 15
INPUT #1, factorial$(a%)
NEXT
CLOSE #1
 
I added the following lines to my code:

DEFDBL A-Z
DIM SHARED total AS DOUBLE
DIM tot AS DOUBLE


I verified by a debug/trace that the SUB simpfact is being called but total is not holding the value I intend to return from the subroutine (which is, of course, the value of the factorial). In other words, A = 0, and since A=0, the BinomialSum is overloaded (division by zero).

What is missing from my code in order to be able to retrieve the value calculated in my subroutine (i.e., why is the subroutine not returning a value for total);How do I specify what value(s) are to be returned by the subroutine when I call it? - this seems to be missing from the documentation.

Thanks for the help and for being patient with a newer, albeit slow, QBASIC student[ponder].
 
The following are all of my dimension statements:

DIM SHARED N AS INTEGER
DIM SHARED K AS INTEGER
DIM SHARED i AS INTEGER
DIM tot AS DOUBLE
DIM SHARED A$(15)


I added the following code block:

DIM SHARED factorial$(15)
OPEN "C:\DOCUME~1\ALLUSE~1\DESKTOP\QBASIC\fact.txt" FOR INPUT AS #1
FOR A%=0 TO 15
INPUT #1, factorial$(A%)
NEXT
CLOSE #1


I eliminated the subroutine and subroutine call and added, after INPUT N,

A$ = factorial$(N%)
j% = N - i
FOR i = K TO N 'this stmt was in the old code'
BinomialSum = A$/(factorial(i%) * factorial(j%)) * ReplyProb ^i * ReplyProb^(N-i)



[COLOR=#ff000]I was not able to load the file, despite using the exact pathname and file.[/color]. I changed the variable A to A$ because of a type mismatch and set the array index j% to the value N-i. I also changed b(i) and c(i) to factorial(i%) and factorial(j%), respectively, hoping that these statements properly index the appropriate factorial values from the text file.

Thanks for the major help, qbasicking and tsh73; I'm still at "QBasic for Idiots" level so if you'd still help me out I would be most grateful.[ponder]
 
Argonath, here's a thing than might help you a bit.
If you have factorials counted (thanks to qbasicking) - you can go without file, just with DATA / READ pair.
BTW, 0!=1 by definition (it used in calculations a lot).

As to "How do I specify what value(s) are to be returned by the subroutine when I call it? - this seems to be missing from the documentation."
- use a FUNCTION, it is supposed to return values.
If you need to return value from SUB you can either put this value as parameter (it would serve as return parameter), or use global variable (COMMON SHARED piece).

Last program of yours will not work because
j% = N - i
happens to be out of loop (FOR thing) that changes "i".

I don't get what math problem you are going to solve, so I set up binominal coeffts example.

Code:
DEFDBL A-Z
DATA 1,1,2,6,24,120,720,5760,51840,518400,5702400,68428800
DATA 889574400,12454041600,186810624000

DIM SHARED factorial(15)

FOR i = 0 TO 14
READ factorial(i)
NEXT

FOR i = 0 TO 14
PRINT factorial(i)
NEXT

PRINT
PRINT "(a+b)^n=sum Cn,k*a^k*b^(n-k)"
PRINT "Cn,k=n!/(k!*n-k!)"
PRINT

n = 10
PRINT "(a+b)^"; n; "="
PRINT "b^"; n
FOR k = 1 TO n - 1
Cnk = factorial(n) / (factorial(k) * factorial(n - k))
PRINT "+"; Cnk; "*a^"; k; "*b^"; n - k
NEXT
PRINT "+a^"; n

Note, array "factorial" here used like a function.
Hope this helps.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top