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
COMBO 14 5 at the DOS prompt, and have
the answer printed on the screen. Here is a workable batch file:

: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 one, 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 great 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 COMBO 8 3, with one or more spaces between the parameters, and almost instantaneously the text ombinations: 56 is output to the screen. Surely enough, 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.

But first, 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 D^2 can be written as D*D, so we will do that (larger or fractional exponents also could be accommodated by the use of 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 FACTOR 16790123457, and up pops a listing of the three prime components: 3 ^ 2 17 ^ 3 379721.

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

It's all a matter of total loops. The more lower-numbered factors, the faster the process will be completed. Should you try FACTOR 167901234579971, it will run for a lot longer time, because that number also is prime. Each extra digit potentially increases the runtime by a factor 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 MATH 380 +16*LOG(27/4) -9.5; the screen will clear, then will display both the problem and its solution: 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 MATH EXP(LOG(3)*4.5). The answer will be displayed: 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

Computer programming

GW-BASIC

BASIC programming shortcuts

Batch files

BASIC function calls

sort routines

shuffling routines

Boolean logic arithmetic