Magic with BASIC in Batch Files |

Let us assume that you spend a lot of time at the DOS prompt.
Either your PC is old and slow, or you have a ~~DOS-capable~~
~~hand-held~~ device, or you prefer to perform ~~file-maintenance~~
tasks in a DOS window, ~~or —~~ heaven ~~forbid —~~
you simply love DOS. Anyone who programs in BASIC should fall into
one of these categories.

Creating your own program is great, but having to load the BASIC
Interpreter in order to execute the code might not be so great.
If all that you desire is some sort of little utility that performs a
short task, then the hassle might not be worth it. If you cannot
compile your code, or you need to limit the file sizes, then your options
are limited. Also, there is no way to supply ~~command-line~~
instructions to the BASIC Interpreter. What can you do?

One solution is the batch file. It is possible to run
~~GW-BASIC,~~ load and execute a program with parameters supplied
at the DOS prompt, close down BASIC, delete temporary files, and return
control to the DOS ~~prompt —~~ all within a fraction of a
second, and with all internal activity transparent to the user!
Moreover, it's ~~easy —~~ and fun.

Here is one way to accomplish the mission:

- Create a batch file to input any desired parameters and store them in a temporary file.
- Write a BASIC program that performs the desired task. It also will need to open and read the parameter file, and know what to do with the data.
- Have the batch file delete the temporary files, then exit.

Let's try a simple example. Either you are studying probability
in school, or you play a lot of fancy keno tickets. So you have
occasion to calculate the combinations of **N** things,
taken **R** at a time. (Example: if you have
~~5 marbles~~ of different colors, how many ~~2-color~~ combination
are there?) The objective is to be able to enter something such
as at the DOS prompt, and have the answer
printed on the screen. Here is a workable batch file:COMBO 14 5

:COMBO.BAT (combinations of N things R at a time)

@echo off

set f=c:\temp\parm

echo %1 > %f%

echo %2 >> %f%

gwbasic c:\prgmfile\combo

del %f%

set f=

This page is not intended as a tutorial on batch-file protocols, as that information can be found on a batzillion other pages; nevertheless, I will explain briefly:

- Yes, I have used a colon, rather than "rem," to start a
title line. Big deal. It doesn't hurt anything to create
a label that never is used as such, and it's much
~~cleaner-looking.~~If it makes you feel better, use a~~double-colon;~~such lines are ignored by DOS. In any case, I hate seeing the word "rem" cluttering my listings; so I never use it to comment anything. REM does have one useful function, though, as we shall see later. - Variable
**f**is set equal to the path of the output file. This is not required, but it cleans up some subsequent lines. - %1 and %2 are the command-line parameters supplied by the user.
- The echo command is DOS's way of sending data somewhere.
- The first redirect symbol (>) means "to" or "into"; it creates a new file with the specified name, even if it already exists.
- The second redirect (>>) means "append to the file", so the second number is added to existing data, starting on a new line.
- BASIC is run, and C:\PRGMFILE\COMBO.BAS is loaded and executed.
- Finally, the temporary file and environment variable are erased, and the process is complete.

Now, let's create COMBO.BAS:

10 '---[ Combo = combinations of N things R at a time]--- 11 ' 20 OPEN "i",1,"C:\TEMP\PARM" 30 INPUT$ #1,N$: N=VAL(N$) 40 INPUT$ #1,R$: R=VAL(R$) 49 ' 50 COMBO=N 60 FOR J=2 TO R 70 COMBO=COMBO*(N+1-J)/J 80 NEXT J 89 ' 90 PRINT "Combinations:" COMBO 99 SYSTEM

Place this file in the directory indicated in the batch file,
and you are ready to test your new system. At the DOS prompt,
enter with one or more spaces
between the parameters, and almost instantaneously the text
COMBO 8 3

, is output to the screen.
Surely enough, Combinations: 56

~~8 items~~ can be selected ~~3 at~~ a time
~~in 56~~ unique ways. It works!

Observe, however, that the input must make sense. Should you
enter something other than integers,the result will be nonsensical.
Garbage in, garbage out. ~~Error-trapping~~ of input always
is desirable, and we'll do some of that in the next exercise.

This routine can easily be augmented to include calculations for Permutations and Factorials. I have done that in a file available for downloading (see end of page).

This next project is admittedly an esoteric one. If you are
comfortable with BASIC and not with batch files, then you might prefer
to stick with the method just covered. However, those interested
in ~~batch-file~~ programming will find this method more interesting.

The goal is to create a system that extracts the prime factors of an integer. That will be more fun than calculating combinations. However, unlike COMBO, the BASIC program will be created within the batch file itself! The procedure is somewhat more complicated, but it results in a cleaner setup in that there is no BASIC program to store. Here is our simple algorithm:

- An integer X is divided by 2 as many times as possible, then by the successive odd numbers.
- The procedure continues until either X is reduced to a value of 1, wherein factoring will be complete, or the square root of X is reached by the divisor, indicating that X is prime.
- Output will list the prime factors, plus any exponents greater than 1.

In the most efficient setup, the divisors would be the successive
primes; but that really isn't necessary for our purposes. You will find
that factoring integers up ~~to 11~~ ~~or 12~~ digits runs plenty
fast even with this minimal structure, and without being compiled.
The crux of our algorithm:

{ N is the number to be factored. X is set equal to N. D is the divisor. E is the exponent }

300 WHILE X>=D^2 AND X>1 310 D=D+1-(D<>2): E=0 320 IF X/D=INT(X/D) THEN X=X/D: E=E+1: GOTO 320 330 IF E THEN F$=F$+""+STR$(D) 340 IF E>1 THEN F$=F$+"^"+RIGHT$(STR$(E),LEN(STR$(E))-1) 350 WEND 399 ' 400 IF X<>N AND X<>1 THEN F$=F$+""+STR$(X) 410 IF X<>N THEN PRINT "Prime factors:" F$ 420 IF X=N THEN PRINT TAB(3); N; "is prime." 430 END

Before writing the batch file, let us establish another couple of useful protocols. Let's decide to name all temporary files as "$----"; that way, they always will be recognizable as such. Let's also plan always to put them in the directory C:\TEMP (or whatever you prefer). It also is useful to include a Help screen in the batch file, lest the user forget what the program does or how the input should be structured.

Firstly however, there are a couple of snags to overcome.
The BASIC '**>**' and '**<**' symbols cannot be used as text
within a batch file, unless they are enclosed in quotes. Also, the
crummy ~~DOS-equivalent~~ featured in Windows XP chokes on (that is,
ignores) the carat '**^**' symbol, unless it also is inside quotes.
Earlier versions of Windows didn't have this problem; eventually,
Microsoft will succeed in eliminating the Windows ~~command-prompt~~
entirely, which will force us DOS lovers to set up a ~~dual-boot~~
system with DOS ~~6.22~~ or Windows 98. Perhaps you already have
done that; it's easy enough.

Meanwhile, it will be necessary to code exponential functions and
certain relational expressions in other ways. An expression such
as can be written as **D^2** so we will do
that (larger or fractional exponents also could be accommodated by
the use of **D*D**,**LOG** and **EXP**). Relational expressions can
be converted to something workable by judicious use of the
~~absolute-value~~ construct.

While we're at it, let's include a little Help screen. Here is a working batch file:

:FACTORS.BAT (extracts prime factors)

@echo off

if %1!==! goto Help

set f=c:\temp\$factors.bas

echo 1 defdbl a-z: n=%1: x=n: color 14,1:
? > %f%

echo 2 while x-d*d = abs(x-d*d): e=0: if d=2
then d=3 else d=d+2 >> %f%

echo 3 if x/d = int(x/d) then x=x/d: e=e+1: goto 3
>> %f%

echo 4 if e then ? d;: if e-2 =
abs(e-2) then ? "^" E; >> %f%

echo 5 wend: ? x;: if x=n then ? "is prime." >>
%f%

echo 6 system >> %f%

gwbasic.exe %f%

del %f%

set f=

goto End

:Help

echo.

echo Usage: FACTORS positive integer (15-digit max)

echo.

:End

Explanation:

- The extra spacing in the program code is solely for readability on this page. Ideally, all redundant spaces would be eliminated. Combining program statements on lines saves time for both DOS and BASIC.
- Testing for existence of a parameter (%1) directs control to the Help section when none was entered.
- The temporary program will be $FACTORS.BAS.
- DEFDBL eliminates the need to flag variables as X#, Y#, etc.
- 1. N is the integer to be factored, and a nice yellow-on-blue output is selected.
- 1. The smaller the program, the faster it will load. GW-BASIC expands any '?' character to 'PRINT' as it loads the file.
- 2. '>=' cannot be used; substituting 'X-D*D = ABS(X-D*D)' guarantees that X > D^2.
- 2. The exponent is initialized at 0.
- 3. X is tested for divisibility by D, and the exponent E is
incremented. This line combines the BASIC lines 340 and 350.
The program runs
__much__faster this way. I separated them in the BASIC listing only for readability. - 4. The expression 'E-2 = ABS(E-2)' fails if E<2. Showing an exponent of 1 would be redundant.
- 5. 'IF X=N' determines whether any divisions have been made.

I did promise some error-trapping capability, so let us finish up by
restricting user input to as appropriate number. ~~GW-BASIC~~
~~double-precision~~ stores ~~17 digits,~~ but will print
~~only 16.~~ My testing has shown that this routine fails on
certain ~~16-digit~~ numbers; so let us arbitrarily limit the size
to ~~15 digits.~~ Also, negative numbers and ~~non-integers~~
are unacceptable. Here is an updated program, which will catch most
errors:

:FACTORS.BAT (extracts prime factors)

@echo off

if %1!==! goto Help

set d=c:\temp\

set f=$factors.bas

echo 1 on error goto 10: if not %1-2 =
abs(%1-2) goto 10 > %f%

echo 2 if not %1 = int(%1) goto 10 >> %f%

echo 3 z=log(1E+15): if not z-log(%1) = abs(z-log(%1)) goto 10
>> %f%

echo 4 defdbl a-z: n=%1: x=n: color 14,1:
? > %f%

echo 5 while x-d*d = abs(x-d*d): e=0: if d=2 then
d=3 else d=d+2 >> %f%

echo 6 if x/d = int(x/d) then x=x/d: e=e+1: goto 6 >>
%f%

echo 7 if e then ? d;: if e-2 = abs(e-2)
then ? "^" E; >> %f%

echo 8 wend: ? x;: if x=n then ? "%1 is prime."
>> %f%

echo 9 system >> %f%

echo 10 shell "rem > %d%$err":
system >> %f%

gwbasic.exe %f%

if not exist %d%$err goto Cleanup

:Help

echo.

echo Usage: FACTORS positive integer (15-digit max)

echo.

:Cleanup

if exist %d%$*.* del %d%$*.*

set f=

set d=

Explanation:

- 1 An ON ERROR statement is useful in any program, as a way of
trapping unanticipated errors. The
~~'%1-2 = abs(%1-2)'~~guarantees that N is greater than 1. - 2 '%1 = int(%1) fails if N is not an integer.
- 3 Having decided that 10^15-1 is the largest permissible integer. Execution is terminated if the logarithm of N is greater than that of the maximum, indicating that N is too large.
- In BASIC, these three conditions could have been trapped easily by a
statement such as,
~~'IF N<1 OR N >= 10^15 OR N <> INT(N)';~~The restrictions on usage of "<" and ">" necessitated creative measures. - 10 If any error is detected, line 10 creates the file $ERR as
a way of telling DOS that an error was encountered. The usage of
REM here is an undocumented method for creating a file of zero length.
We don't care what's in the
~~file —~~merely that it exists. - After BASIC quits, the batch file checks for the presence of $ERR. If it is there, the Help screen is printed.

So there you have it. At the command prompt, enter
, and up pops a listing of the
three prime components:
FACTOR 16790123457

3 ^ 2 17 ^ 3 379721

.

Try it again:
This runs somewhat slower, then produces the message:
FACTOR 16790123473

.16790123473 is prime

.

It's all a matter of total loops. The smaller the factors,
the faster the process will be completed. Should you try
it will run for a lot
longer time, because that number also is prime. Each extra digit
potentially increases the runtime by a factor FACTOR 167901234579971

,~~of 5.~~
This particular calculation requires ~~12 seconds~~ on my PC,
even when compiled; but anything up to ~~13 digits~~ spits out a
solution immediately.

I include two other utilities that you might find useful:

– MATH.BAT –

Do you miss the ability to actually calculate something
from the DOS prompt? Now you can. Virtually any math problem
that BASIC can understand may be entered at the DOS prompt.
For example, enter
the screen will clear, then will display both the problem and its
solution:
MATH 380 +16*LOG(27/4) -9.5

;380 +16*LOG(27/4) -9.5 = 372.4096

.

Enter MATH by
itself for a listing of all the available functions, plus a couple of
extras, such as using P=pi and R=radians. But remember the legacy
of XP; the carat (**^**) cannot be used. To calculate, for
example, ~~3^4.5,~~ enter
The answer will be displayed: MATH EXP(LOG(3)*4.5)

.140.2961

.

– AMORT.BAT –

With this one, you simply enter an amount to finance, interest rate, and term, and it will display the monthly charge on the principal.

*Download:***Batches.zip**
All four batch files