how to use goto in batch script - batch-file

I have written following code
setlocal
set /A sample =1
:first
type C:\test.txt | find "inserted"
if %ERRORLEVEL% EQU 0 goto test
if %ERRORLEVEL% EQU 1 goto exam
:test
echo "testloop" >> C:\testloop.txt
set /A sample = %sample% + 1
if %sample% LEQ 4 goto first
:exam
echo "exam loop" >> C:\examloop.txt
endlocal
but it is going to lable "exam" even though error level is not equal to "1" plz help me

Your problem isn't goto, its that errorlevel requires special treatment, it's not like an ordinary environment variable. The only test you can do with errorlevel is to test whether it is greater than or equal to value.
so you have to test errorlevel values from highest to lowest because if errorlevel 1
then if errorlevel 1 will be true, but if errorlevel 0 will also be true
setlocal
set /A sample =1
:first
type C:\test.txt | find "inserted"
if errorlevel 1 goto exam
if errorlevel 0 goto test
:test
echo "testloop" >> C:\testloop.txt
set /A sample = %sample% + 1
if %sample% LEQ 4 goto first
:exam
echo "exam loop" >> C:\examloop.txt
endlocal
if you have command extensions enabled, and there is no environment variable called ERRORLEVEL (case insensitive). Then in theory you can use %ERRORLEVEL% like an ordinary environment variable. So this should also work
setlocal EnableExtensions
set /A sample =1
:first
type C:\test.txt | find "inserted"
if %errorlevel% EQU 1 goto exam
if %errorlevel% EQU 0 goto test
:test
echo "testloop" >> C:\testloop.txt
set /A sample = %sample% + 1
if %sample% LEQ 4 goto first
:exam
echo "exam loop" >> C:\examloop.txt

You need to list the error levels in descending order (errorlevel2, errorlevel1, errorlevel0...).
See this explanation and example.

You may want to consider using ERRORLEVEL as direct branching as follows:
setlocal
set /A sample =1
:first
type C:\test.txt | find "inserted"
**goto :Branch%ERRORLEVEL%**
:Branch0
echo "testloop" >> C:\testloop.txt
set /A sample = %sample% + 1
if %sample% LEQ 4 goto first
:Branch1
echo "exam loop" >> C:\examloop.txt
endlocal

May be use || instead of errorlevel for branching.
setlocal
set /a sample=1
:first
(Type c:\test.txt | find "inserted" >> c:\testloop.txt) || goto :branch1
set /a sample+=1
If %sample% leq 4 goto :first
:brabch1
Echo "exam loop" >> c:\examloop.txt

More simple way to use for loop.
For /l %%a in (1,1,4) do (
(Type c:\test.txt | find “inserted” >> c:\testloop.txt) || goto :done
)
:done
Echo “exam loop” >> c:\examloop.txt
Goto :eof

Related

is there any way to don't have to check every state between 2 numbers in batch?

i was creating a rock paper siscors game in batch, i finisced and i wanted to "clean it", becouse it checked every possible combination between the 3 numbers rappresenting rock paper siscors, but i don't know what to do
at first i tried, instead of checking every equal number, i used the "equ" operator, but after that i didn't know what to do, i tried once by making the bigger number the winner, and checked if they were a 0 (paper) and 2 (rock) to make rock weaker than paper on the same "if" function, but the terminal just crashed.
i don't know how to do it somwhere else and then check after, i started using batch yesterday, so i dont know praticaly anything.
also if i did any error while typing correct me becouse english is not my first language
#echo off
color f
cls
echo welcome to rock paper siscors
:LOOP
echo 0=(paper) 1=(siscors) 2=(rock)
set /p input= select one of the 3:
set /a cpu=%random% %%3
if %input% GTR 2 (echo don't type values bìigger than 2!!!!!!!!!!!!!!)
if %cpu% equ 0 if %input% equ 1 (echo you win!)
if %cpu% equ 0 if %input% equ 2 (echo you lose!)
if %cpu% equ 1 if %input% equ 0 (echo you lose!)
if %cpu% equ 1 if %input% equ 2 (echo you win!)
if %cpu% equ 2 if %input% equ 0 (echo you win!)
if %cpu% equ 2 if %input% equ 1 (echo you lose!)
if %cpu% equ %input% (echo parity!)
if %cpu% equ 0 (echo the cpu selected paper)
if %cpu% equ 1 (echo the cpu selected siscors)
if %cpu% equ 2 (echo the cpu selected rock)
goto :LOOP
Mmm.. These are my thoughs...
Scissors 1 win to Paper 0. Rock 2 win to Scissors 1; but Rock 2 should lose vs Paper. This means that Paper=0 should become Paper=3 IF the opponent is Rock 2. That is:
cpu += (!cpu) * !(input-2) * 3
We will do an extensive use of ! (Boolean NOT) operator, that returns a 1 if its operand is zero, and returns a zero in any other case. In this way, !cpu is 1 if cpu is Paper and is zero in any other case (scissors or rock).
In the same way (input-2) is zero only when input is rock, so !(input-2) returns one only when input is rock (and zero in any other case).
This means that (!cpu) * !(input-2) gives 1 when cpu is Paper AND input is Rock (and 0 in any other case). If you multiply this value times 3 (!cpu) * !(input-2) * 3 and add such a value to cpu: cpu += (!cpu) * !(input-2) * 3 then this expression will convert cpu from Paper=0 to Paper=3 when input is Rock. Ta-Da! :)
We must apply the same treatment to input when it is Paper and cpu is Rock, that is:
set /A cpu += (!cpu) * !(input-2) * 3
set /A input += (!input) * !(cpu-2) * 3
There is no way that both above expressions be executed on the same data, so it is not necessary to insert any IF to prevent to execute one or the other expression.
Also, it is simpler to get the user input via choice command that directly gives a 1..3 result, so we subtract 1 from its returned ERRORLEVEL in order to manage our standard values: 0=Paper, 1=Scissors and 2=Rock:
set /A "cpu=%random% %% 3"
choice /C PSR /N /M "Select [P]aper, [S]cissors or [R]ock: "
set /A "input=%errorlevel% - 1"
set /A "cpu += (!cpu) * !(input-2) * 3"
set /A "input += (!input) * !(cpu-2) * 3"
if %cpu% gtr %input% (echo you lose) else ...
But the SET /A command can execute several operations separated by comma, so above 4 expressions could be given in a single SET /A command. Also, we can get the name of each item via an array of names that can directly give the desired element in a single operation. Here it is the whole thing:
#echo off
setlocal EnableDelayedExpansion
rem Define the "items" array
set "item[0]=Paper" & set "item[1]=Scissors" & set "item[2]=Rock" & set "item[3]=Paper"
:LOOP
choice /C PSR /N /M "Select [P]aper, [S]cissors or [R]ock: "
set /A "input=%errorlevel%-1, cpu=%random% %% 3, cpu+=(^!cpu)*^!(input-2)*3, input+=(^!input)*^!(cpu-2)*3"
if %cpu% gtr %input% (
echo you lose
) else if %cpu% equ %input% (
echo parity
) else (
echo you win
)
echo cpu selected !item[%cpu%]!
choice /M "Play again? "
echo/
if not errorlevel 2 goto LOOP
We could also eliminate the IF's commands used to identify the winner via the following trick. If we analyse the possible values of the expression input - cpu, we'll realize that if the result is 2 or 1, you win; if it is 0, is draw; and if it is -1 or -2, you lose. We could directly use these values to define a "result" array with 5 elements this way:
rem Define the "results" array
set "result[2]=you win"
set "result[1]=you win"
set "result[0]=parity"
set "result[-1]=you lose"
set "result[-2]=you lose"
. . .
set /A "res=input-cpu"
echo !result[%res%]!
However, we could diminish the "result" array to just 3 elements if we use the "Sign" function that returns 1, 0 or -1 for positive, zero or negative values, respectively:
set /A "res=input-cpu, res=(res>>31|1)*!!res"
Here it is the final version:
#echo off
setlocal EnableDelayedExpansion
rem Define the "items" array
set "item[0]=Paper" & set "item[1]=Scissors" & set "item[2]=Rock" & set "item[3]=Paper"
rem Define the "results" array
set "result[1]=you win" & set "result[0]=parity" & set "result[-1]=you lose"
:LOOP
choice /C PSR /N /M "Select [P]aper, [S]cissors or [R]ock: "
set /A "input=%errorlevel%-1, cpu=%random% %% 3, cpu+=(^!cpu)*^!(input-2)*3, input+=(^!input)*^!(cpu-2)*3, res=input-cpu, res=(res>>31|1)*^!^!res""
echo !result[%res%]!
echo cpu selected !item[%cpu%]!
choice /M "Play again? "
echo/
if not errorlevel 2 goto LOOP
#ECHO OFF
:again
SET /a cpu=(%RANDOM% %% 3) + 1
SET "result="
SET "player="
choice /c rpsq /m "[R]ock [P]aper [S]cissors [Q]uit "
(
FOR %%e IN (1:Rock 2:Paper 3:Scissors 21 32 13) DO FOR /f "tokens=1,2delims=:" %%b IN ("%%e") DO (
IF %errorlevel%==%%b SET "player=%%c"
IF %cpu%==%%b SET "cpu=%%c"
IF %errorlevel%%cpu%==%%b SET "result=beats"
)
IF %cpu%==%ERRORLEVEL% SET "result=Draws with"
IF NOT DEFINED result SET "result=Loses to"
)
IF DEFINED player ECHO %player% %result% %cpu%&GOTO again
ECHO Quit?
ECHO Scaredy cat!
GOTO :EOF
Here's my version.
First set cpu to a random number 1 to 3
Then use choice to set errorlevel to 1(Rock) 2(Paper) 3(Scissors) or 4(Quit)
Then notice that the next statement (for...%%e...) is parenthesised, so is parsed as a single block
%%e is set to the value of each of the strings in its parentheses in turn
%%b and %%c are set to the string before and after the : delimiter in the string %%e
If %%b = errorlevel as set by the choice, set player to R/P/S
Ditto cpu from the value set by the set /a
set result to beats if {player choice number}{cpu choice number} is mentioned on the for %%e list
If both player and cpu choices are identical, set result to draws with
if result is still not assigned, it's neither a win nor a draw, so it's a loss
If player wasn't set in the loop, then errorlevel set by the choice must be 4 for Quit, otherwise output the three strings and go back to the beginning.
Whilst not a direct fix for your reported problem, here's an rewritten example batch-file to study, and which may better suit your purpose:
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
Color 0F
Echo Welcome to Rock Paper Scissors
:LOOP
Set /A "Opponent=(%RANDOM% %% 3) + 2, Opponent *= Opponent"
%SystemRoot%\System32\choice.exe /C RPS /N /M "[R]ock, [P]aper, or [S]cissors?"
Set /A "Result=Opponent - %ErrorLevel%"
Set "Opponent=Paper"
If %Result% Lss 4 Set "Opponent=Rock"
If %Result% Gtr 8 Set "Opponent=Scissors"
For %%G In (15 6 2) Do If %Result% Equ %%G Set /P "=You WIN: " 0<NUL
For %%G In (14 8 1) Do If %Result% Equ %%G Set /P "=You LOSE: " 0<NUL
For %%G In (13 7 3) Do If %Result% Equ %%G Set /P "=DRAW: " 0<NUL
Echo Opponent chose %Opponent%
%SystemRoot%\System32\choice.exe /M "Would you like to play again"
If Not ErrorLevel 2 Echo(& GoTo LOOP

Getting goto was unexpected at the time

I am currently making a game that has a persuasion system in it. I had all the code for one of the systems set up, but then I set up 2 more, and it started give me an error that said '(number) was not expected at this time'. when I put in 2 for the second choice, and 3 for the 3rd choice.
The code is like this.
#echo off
SETLOCAL EnableDelayedExpansion
for /F "tokens=1,2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do (
set "DEL=%%a"
)
set name=Quantum
cls
color 0a
Echo King Redwood: So 2000?
pause >nul
echo.
call :colorText 09 "1. 2500"
echo.
call :colorText 0e "2. 3000"
echo.
call :colorText 0c "3. 4000"
echo.
echo 4. 2000
echo.
set /p "purs=Enter:"
if /i %purs% == 1 (
goto CheckB )
if /i %purs% == 2 (
goto CheckY )
if /i %purs% == 3 (
goto CheckR )
if /i %purs% == 4 (
goto Convo )
:CheckB
set bleu=%random:~-2,1%
if %bleu% GTR 10 (
goto CheckB )
if %bleu% LSS 0 (
goto CheckB )
set /a num = 3
set /a reward = 2500
goto Res
:CheckY
set Yel=%random:~-2,1%
if %Yel% GTR 10 (
goto CheckY )
if %Yel% LSS 0 (
goto CheckY )
set /a num = 5
set reward = 3000
goto Res
:CheckR
set red=%random:~-2,1%
if %red% GTR 10 (
goto CheckB )
if %red% LSS 0 (
goto CheckB )
set /a num = 7
set /a reward = 4000
goto Res
:Convo
set /a reward = 2000
Echo %name%: I think that is a reasonable price.
Echo King Redwood: Very well.
Echo King Redwood: We will now take you to make sure you are
echo ready.
pause >nul
:Res
if %bleu% GEQ %num% goto Succeed
if NOT %bleu% GEQ %num% goto Fail
:Succeed
Echo %name%: I think that the struggles for such a long trip will be more then that
Echo %name%: How about %reward%?
Echo King Redwod: OK %reward% will work.
pause >nul
goto end
:Fail
Echo %name%: I think that you can give me %reward%.
Echo %name%: You know, for the struggles that there will be along the way.
echo If 2000 isn't good enough for you, I'll just have someone else do it.
pause >nul
:end
exit
:colorText
echo off
<nul set /p ".=%DEL%" > "%~2"
findstr /v /a:%1 /R "^$" "%~2" nul
del "%~2" > nul 2>&1i
First, make sure to close the FOR loop by putting a ) before :CheckB.
For the 'was not expected at this time' error, you're sometimes comparing an empty variable to something. For example, by following CheckY, you set Yel, then proceed to Res and check Bleu, which is empty because it hasn't been set. You're putting nothing next to the binary GEQ operator, and that's why it's complaining.
Tip: to debug, try inserting ECHO statements like this:
:Res
echo bleu=%bleu%,num=%num%
Another problem: when using SET, do not surround the = by spaces. SET /a will work with spaces around =, just because of the nature of /a, but plain SET will not. Well, it will append your variable name with a space and prepend your value with a space, which is not what you want.
Another tip: you can constrain what RANDOM returns through SET /a and the modulus operator, like this.
SET /a red=%random% %% 11
This will set red to a number between 0 and 10, so there is no need for the substrings and goto routines you're using after picking your random number.
Also, consider using EXIT /b to exit the batch file and not the whole CMD environment.

Using the goto command as a fallback in a batch file

How can I make it so that when the folder can't be found, the code will use the goto command?
Here's my code:
:T
Echo Folder is Already Unlocked
:CODE
if attrib -h -s "Control Panel.{21EC2020-3AEA-1069-A2DD-08002B30309B}" goto T
ren "Control Panel.{21EC2020-3AEA-1069-A2DD-08002B30309B}" Codes
call :c 09 " Codes Unlocked successfully
goto UNLOCK
Here's some examples - given as "answers" since the formatting is easier to use
#ECHO OFF
SETLOCAL
:: This one forces errorlevel 0
echo x|find "x" >nul
if errorlevel 1 (echo errorlevel is 1 or greater) else (echo errorlevel is 0)
:: This one forces errorlevel 1
echo y|find "x" >nul
if errorlevel 1 (echo errorlevel is 1 or greater) else (echo errorlevel is 0)
:: Now some multi-line responses
:: This one forces errorlevel 0
echo x|find "x" >nul
if errorlevel 1 (
echo errorlevel is 1 or greater
echo I say again - errorlevel 1 1 or greater
echo I say a third time - errorlevel 1 1 or greater
) else (
echo errorlevel is 0
echo again errorlevel is 0
echo once again errorlevel is 0
)
:: This one forces errorlevel 1
echo y|find "x" >nul
if errorlevel 1 (
echo Y-errorlevel is 1 or greater
echo I say again - errorlevel 1 1 or greater for Y
echo I say a third time - errorlevel 1 1 or greater - Y
) else (
echo Y-errorlevel is 0
echo Y-again errorlevel is 0
echo Y-once again errorlevel is 0
)
:: conditional modification of variable
set /a var=22
echo x|find "x" >nul
if errorlevel 1 (set /a var=%var%+10) else (set /a var=%var%-10)
echo after testing x, var is %var%
set /a var=22
echo y|find "x" >nul
if errorlevel 1 (set /a var=%var%+10) else (set /a var=%var%-10)
echo after testing y, var is %var%
:: You'll need to change these lines to files/directories that exist or don't exist
set "fileexists=c:\pdoxusrs.net"
set "direxists=c:\users"
set "filemissing=c:\missing.net"
set "dirmissing=c:\nothere"
for %%a in ("%fileexists%" "%direxists%" "%filemissing%" "%dirmissing%") do (
if exist "%%~a" (echo "%%~a" exists) else (echo "%%a" missing)
)
goto :eof
Now if errorlevel isn't being set to 0/non-zero as you appear to be expecting, then try using if exist instead. Probably easier that way, actually. Unfortunately "doesn't work" simply means nothing - we'd need to know exactly what happened, and we'd need you to edit your original posting to add-in your current code (or at least, a representative portion.)

How to store ERRORLEVEL in a variable?

I'm trying to store the ERRORLEVEL environment variable into a a local batch variable. But it always turns out to be 0.
CALL foo.exe
SET LEVEL=%ERRORLEVEL%
IF ERRORLEVEL 1 (
SET /A ERRORCOUNT=ERRORCOUNT+1
) ELSE (
SET /A OK=OK+1
)
ECHO/ >> logtemp.txt
ECHO ** EXIT %LEVEL% *******************************
I have tried to ECHO %ERRORLEVEL% but it always print 0 too.
foo.exe is generating an error and it can be seen by ECHO %ERRORLEVEL% from the command prompt and the ERRORCOUNT is updated correctly.
I suppose your problem is not the errorlevel, it's your foo.exe.
A simple test with an errorlevel works.
(call) sets the errorlevel to 1
(call)
SET LEVEL=%ERRORLEVEL%
IF ERRORLEVEL 1 (
SET /A ERRORCOUNT=ERRORCOUNT+1
) ELSE (
SET /A OK=OK+1
)
ECHO/ >> logtemp.txt
ECHO ** EXIT %LEVEL% *******************************
Second sample:
if 1==1 (
call set level=%%errorlevel%%
call echo %%level%%
call echo %%errorlevel%%
echo %errorlevel%
)
Or with delayed expansion
setlocal EnableDelayedExpansion
if 1==1 (
set level=!errorlevel!
echo !level! !errorlevel!
)
ERRORLEVEL and %ERRORLEVEL% are not the same (see http://blogs.msdn.com/b/oldnewthing/archive/2008/09/26/8965755.aspx).
The line
IF ERRORLEVEL 1
should be
IF %ERRORLEVEL% EQU 1
to yield the desire answer.

Prime numbers in batch

I've been working on a little project using batch files and I've ran into a problem. As far as I'm aware there's no way to run a check to see if a certain variable is a prime number, if I'm wrong would anyone please inform me of how to do so, otherwise, can anyone think of a workaround I could use (like checking if a number is equal to a number on a list of prime numbers on a txt file or whatever).
Thanks ^^
(Also it's worth noting I'm not very knowledgeable with batch files so please excuse any idiocy I may present..)
If you have a text file of prime numbers, 1 per line (obviously up through some limit), then the solution is trivial - just use FINDSTR.
Assuming you have a NUMBER variable containing a number, then
>nul findstr /x %NUMBER% "primes.txt" && (
REM prime actions go here
echo %NUMBER% is prime
) || (
REM not prime actions go here
echo %NUMBER% is NOT prime
)
UPDATE
Here is a native batch script that can test any valid integer supported by batch (signed 32 bit ints) to see if it is prime. Performance is much better than I thought possible.
::testPrime Number
::
:: Computes whether Number is a prime or not.
:: The result is printed to stdout.
::
:: ERRORLEVEL is also set to indicate the result:
:: 0 = Prime
:: 1 = Not Prime
:: 2 = Error
::
:: Number = Any valid integral expression supported by SET /A
::
#echo off
if "%~1"=="test" (
setlocal enableDelayedExpansion
for /l %%N in (3 2 0x7fffffff) do (
set /a "test1=num %% %%N, test2=%%N*%%N"
if !test1! equ 0 exit 1
if !test2! gtr !num! exit 0
)
)
setlocal disableDelayedExpansion
2>nul set /a "num=%~1" || (
>&2 echo invalid number: %1
exit /b 2
)
if %num% leq 1 (
echo %num% is NOT prime
exit /b 1
)
if %num% leq 3 (
echo %num% is prime
exit /b 0
)
2>nul set /a "1/(num %% 2)" || (
echo %num% is NOT prime
exit /b 1
)
(
cmd /c "%~f0" test
) && (
echo %num% is prime
exit /b 0
) || (
echo %num% is NOT prime
exit /b 1
)
exit /b
The test is actually split into 2 parts, the 2nd of which is actually run in a new CMD instance. The 2nd part actually appears at the top of the script. This is done for performance reasons. It is the only way I can break out of a FOR /L loop immediately without terminating the batch script.
You can integrate your code with the script easily enough. For example:
#echo off
::----------------------------------------------------
:: This 2nd part of :testPrime must be at top of script
::
if "%~1"=="test" (
setlocal enableDelayedExpansion
for /l %%N in (3 2 0x7fffffff) do (
set /a "test1=num %% %%N, test2=%%N*%%N"
if !test1! equ 0 exit 1
if !test2! gtr !num! exit 0
)
)
:: End of 2nd part of :testPrime
::-----------------------------------------------------
:: Your code goes here
:: I'll just call the test with some representative values
::
setlocal disableDelayedExpansion
for %%N in (
1 2 3 4 100001 100003 5000009 5000011 0x7fffffff-2 0x7fffffff
) do >nul call :testPrime %%N && (
rem prime number actions go here
echo %%N is prime!
) || (
rem non-prime number actions go here
echo Not prime (%%N^)
)
exit /b
::----------------------------------------------------
:: Here is the 1st part of :testPrime
::
:testPrime
2>nul set /a "num=%~1" || (
>&2 echo invalid number: %1
exit /b 2
)
if %num% leq 1 (
echo %num% is NOT prime
exit /b 1
)
if %num% leq 3 (
echo %num% is prime
exit /b 0
)
2>nul set /a "1/(num %% 2)" || (
echo %num% is NOT prime
exit /b 1
)
(
cmd /c "%~f0" test
) && (
echo %num% is prime
exit /b 0
) || (
echo %num% is NOT prime
exit /b 1
)
exit /b
The output for the above looks like this:
Not prime (1)
2 is prime!
3 is prime!
Not prime (4)
Not prime (100001)
100003 is prime!
Not prime (5000009)
5000011 is prime!
Not prime (0x7fffffff-2)
0x7fffffff is prime!
Finally, just for yucks, I wrote a variation that lists the next prime >= or <= a given number.
::nextPrime [/less] Num
::
:: List the minimum prime number >= Num
::
:: The /L option lists the maximum prime number <= Num
::
:: The ERRORLEVEL is set to the found prime number
::
:: Num = Any valid integral expression supported by SET /A
::
#echo off
setlocal enableDelayedExpansion
if "%~1"=="test" (
for /l %%N in (3 2 0x7fffffff) do (
set /a "test1=%2 %% %%N, test2=%%N*%%N"
if !test1! equ 0 exit 1
if !test2! gtr %2 exit 0
)
)
if "%~1"=="prev" (
if !num! lss 2 exit 0
set /a "test=num%%2"
if !test! equ 0 set /a num-=1
for /l %%N in (!num! -2 2) do cmd /c "%~f0" test %%N && exit %%N
exit 0
)
if "%~1"=="next" (
if !num! lss 2 exit 2
set /a "test=!num!%%2"
if !test! equ 0 set /a num+=1
for /l %%N in (!num! 2 0x7fffffff) do cmd /c "%~f0" test %%N && exit %%N
exit 0
)
set "cmd=next"
if /i "%~1" equ "/L" (
set "cmd=prev"
shift /1
)
2>nul set /a "num=%~1" || exit /b 0
cmd /c "%~f0" %cmd% || echo !errorlevel!
And here is a demonstration of usage with output:
D:\test>nextPrime 10000000
10000019
D:\test>nextPrime /l 10000000
9999991
All of those scripts seem awfully (and unnecessarily) large to me.
An easier way to do this is using... I believe the term I'm looking for is either modulo or modulus expressions (I think modulo is the plural or modulus).
#echo off & setlocal enabledelayedexpansion
:a
cls
set /p num=Type a number to be checked:
cls
set num2=%num%-1
if %num% leq 2 goto yes
for /l %%i in (2,1,%num2%) do (
set rem=%num% %% %%i
if %rem% neq 0 goto no
)
:yes
echo %num% is a prime number.
pause
goto a
:no
echo %num% is not a prime number.
pause
goto a
Basically, it gets a user-defined variable and checks, when divided by a number, if the remainder (rem) is 0 or not.
This way is a little slow, but the shortest code. You can make it a bit shorter by putting another if statement before the for loop that checks if the number has a remainder when divided by two.
Hope it helps.
Another prime lister, this one does'nt use a file and can reach 64,000,000 if you have patience. Keeps a list of prime divisors in an environment variable. If i had a batch integer square root routine i could make it faster.
#echo off
::batch prime list up to 64M by Antoni Gual
:: does not use files!!
setlocal enabledelayedexpansion
set bitmap=
set n=Y
set /a test=3,npri=3
echo 1th prime is 2 & echo 2th prime is 3
:nextpri
set /a test+=2,index=0,div=3
if %test% LSS 8000 set bitmap=%bitmap%%n%
if %test% gtr 64000000 exit /b
:nextest
if "!bitmap:~%index%,1!"=="N" goto nextdiv
set /a resi=!test!%%!div!
if %resi% equ 0 set n=N& goto nextpri
:nextdiv
set /a index+=1, div+=2
set /a div2=div*div
if %div2% gtr %test% (
set n=Y
echo %npri%th prime is %test%
set /a npri+=1
goto nextpri)
goto nextest
The following script does not perform a primality test. Rather, it generates prime numbers up to a specific bound (the hard-coded 1000 in this particular case). You could generate the list once and then use it in your script(s):
#echo off
echo 2
echo 3
echo 2 > primenos.txt
echo 3 >> primenos.txt
set current=3
:numbercalc
set tim=3
set /a max=%current%/5
:try
set /a t=%current%/%tim%
set /a u=%t%*%tim%
if %u% EQU %current% goto noprime
set /a tim+=2
if %tim% GTR %max% goto endtry
goto try
:endtry
echo %current%
echo %current% >> primenos.txt
:noprime
set /a current+=2
if %current% GTR 1000 goto end
goto numbercalc
:end
pause
Taken from here...
Assuming you have a text file with prime numbers (each number in a single line) you could do it like this:
#echo off
if "%1"=="" (echo Syntax: %~nx0 number & exit /b 2)
for /F "tokens=*" %%p in (primes.txt) do (
if %%p EQU %1 (
echo %1 is prime!
exit /b 0
)
)
echo %1 is not prime!
exit /b 1
Example call: isprime.cmd 2 would give you 2 is prime!.
Here is what I made. It finds all prime numbers up to 214748 but it is accurate and fast and outputs the results to a file called "pn.txt" and the current number to "cn.txt" (this was to let me know what its limit was):
(#echo off)&((set n=3)&((set tn=%n%)&((set d=2)&((set d2=)&((set m=100)&((echo.prime-numbers>pn.txt)&((echo. >>pn.txt)&((echo.1>>pn.txt)&((echo.2>>pn.txt)&((echo.1)&((echo.2)&(goto a))))))))))))
:a
(echo.%n%cn.txt)&((set tn=%n%)&(set tn=%n:~-1%))
(if %tn%==2 ((set /a n=%n%+1)&((set d=2%d2%)&(goto a))))&((if %tn%==4 ((set /a n=%n%+1)&((set d=2%d2%)&(goto a))))&((if %tn%==6 ((set /a n=%n%+1)&((set d=2%d2%)&(gotoa))))&((if %tn%==8 ((set /a n=%n%+1)&((set d=2%d2%)&(goto a))))&((if %tn%==0 ((set /a n=%n%+1)&((set d=2%d2%)&(goto a))))&(goto b)))))
:b
((set /a tn=%d%*%d%)&(if /i %tn% equ %n% ((set /a n=%n%+1)&((set d=2%d2%)&(goto a)))))&((if /i %tn% gtr %n% ((set tn=%n%)&((set l=%d%)&((if /i %n% equ 10000 (set d2=0))&((if /i %n% equ 100000 set (d2=00))&((set d=2%d2%)&((set m=100%d2%)&(goto d)))))))&((set /a d=%d%+1)&(goto b))
:d
(title verifing %n% at %d%)&(set tn=%n%)
set /a tn=%tn%*%m%
set /a tn=%tn%/%d%
set tn=%tn:~-2%
(if /i %tn% equ 00%d2% ((set /a n=%n%+1)&((set d=2%d2%)&(goto a))))&(((set /a tn=%n%-1)&(if %d%==%tn% ((echo.%n%)&((echo.%n%>pn.txt)&(((set /a n=%n%+1)&((set d=2%d2%)&(goto a)))))))&(if %d%==%l% ((echo.%n%)&((echo.%n%>pn.txt)&((set /a n=%n%+1)&((set d=2%d2%)&(goto a)))))))&((set /a d=%d%+1)&(goto d)))
#echo off
::PRIMES
set multiple2=1
set add=1
set counter=1
color f0
set /p range=Computer primes 0-?:
set /a limit=(range/2)+1
set ut=3
mkdir prime0-%range%
cd prime0-%range%
echo >>2
:opipe
echo >>%ut%
set /a ut=ut+2
if %ut% GEQ %range% goto next
goto opipe
:next
set /a multiple2=multiple2+2
if %multiple2% GEQ %limit% goto end
set /a add=add+2
set /a multiple=multiple2
:process
set /a multiple=multiple+add
del %multiple%
if %multiple% GEQ %range% goto next
goto process
:end
CD ..
echo 2 >>ALLprime0-%range%.txt
:offx
set /a counter=counter+2
if exist prime0-%range%\%counter% echo %counter% >>ALLprime0-%range%.txt
if %counter% GEQ %range% goto down
goto offx
:down
echo Computation Succesful
pause
exit
::RMDIR /S /Q prime0-%range%
Please excuse me for beating a dead horse. Here is a radically differnt approach to generating primes in pure batch that overperforms everything else I have found .
It's based in Keeping a list of multiples of previous found primes around the window we're checking. The numbers not found in the list are primes. For keeping the list I use environment variables of the form #composite=next_increment .It uses a single loop, much faster and degrading slower than the nested double loop used in other algorithms. Unforunately a FOR and an auxiliar subrputine are required to overcome the impossiblilty of having repeated keys in environment, as sometimes multiples of different primes clash.
BTW the idea comes from an exerciste in Knuth's TAOCP Vol 3 page 617.
:: prime table using rotating multiples stored in environment
#echo off
setlocal enabledelayedexpansion
mode con cols=90
set #25=-10
set /a num=7,inc1=4,cnt=0,inc2=0,num1=0, maxprime=10000
set lin= 0:
call:line 2 & call:line 3 & call:line 5
:nextnum
if defined #%num% (
for %%i in (!#%num%!) do (
if %%i lss 0 (set /a num1=%num%-%%i,"inc2=-%%i<<1") else (set /a num1=%num%+%%i,"inc2=-(%%i>>1)")
call :aux !num1! !inc2!
)
set #%num%=
) else (
call :line %num%
set /a num1= num * num
if %inc1% equ 4 (set/a "inc2=num<<2") else (set /a "inc2=-(num<<1)")
if !num1! leq %maxprime% set #!num1!=!inc2!
)
set /a num+=inc1, inc1=6-inc1
if %num% lss %maxprime% goto nextnum
echo %lin%
pause & goto:eof
:aux
if %1 leq %maxprime% set #%1=%2 !#%1!
goto:eof
:line formats output in 10 right aligned columns
set num2= %1
set lin=%lin%%num2:~-8%
set /a cnt+=1,res1=(cnt%%10)
if %res1% neq 0 goto:eof
echo %lin%
set cnt1= %cnt%
set lin=%cnt1:~-5%:
goto:eof
#echo off
:top
set /p number=number:
set /a check=1
:work
set /a check=%check%+1
set /a result=%number%/%check%
set /a abc=%result%+1
if %abc% LSS %check% goto end
SET /a modulo=%number% %% %check%
IF %modulo%==0 (goto factor
) ELSE (goto notfactor
)
:factor
echo %check%
set /a other= %number%/%check%
echo %other%
echo.
goto work
:notfactor
goto work
:end
echo If you see 2 numbers this its a prime otherwise its composit
echo.
echo i am too lazy to code it further and have already spend way too much time trying to make this
pause
cls
goto top
this will also tell the prime factors if any.

Resources