我一直在使用批处理文件进行一个小项目,但遇到了问题。据我所知,没有办法检查某个变量是否是素数,如果我错了,请告诉我如何操作,否则,谁能想到我的解决方法可以使用(例如检查一个数字是否等于 txt 文件中素数列表中的一个数字或其他)。谢谢^^(另外值得注意的是我对批处理文件不是很了解,所以请原谅我可能提出的任何白痴..)
9 回答
如果您有一个素数文本文件,每行 1 个(显然超过了一些限制),那么解决方案很简单 - 只需使用 FINDSTR。
假设您有一个包含数字的 NUMBER 变量,那么
>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
)
更新
这是一个本机批处理脚本,可以测试批处理支持的任何有效整数(带符号的 32 位整数)以查看它是否为素数。性能比我想象的要好得多。
::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
测试实际上分为两部分,其中第二部分实际上是在一个新的 CMD 实例中运行。第二部分实际上出现在脚本的顶部。这样做是出于性能原因。这是我可以在不终止批处理脚本的情况下立即跳出 FOR /L 循环的唯一方法。
您可以轻松地将代码与脚本集成。例如:
@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
上面的输出如下所示:
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!
最后,只是为了恶心,我写了一个变体,列出了下一个素数 >= 或 <= 给定的数字。
::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!
这是一个使用输出的演示:
D:\test>nextPrime 10000000
10000019
D:\test>nextPrime /l 10000000
9999991
所有这些脚本对我来说似乎都非常大(而且不必要)。
一个更简单的方法是使用......我相信我正在寻找的术语是模数或模数表达式(我认为模数是复数或模数)。
@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
基本上,它获取一个用户定义的变量,并在除以一个数字时检查余数 (rem) 是否为 0。
这种方式有点慢,但代码最短。您可以通过if
在for
语句检查数字在除以 2 时是否有余数。
希望能帮助到你。
另一个primer lister,这个不使用文件,如果你有耐心的话可以达到64,000,000。在环境变量中保留一个素数除数列表。如果我有一个批处理整数平方根例程,我可以让它更快。
@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
以下脚本不执行素数测试。相反,它会生成一个特定范围内的素数(在这种特殊情况下是硬编码的 1000)。您可以生成一次列表,然后在您的脚本中使用它:
@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
取自这里...
@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%
这是我做的。它可以找到最多 214748 的所有素数,但它准确而快速,并将结果输出到一个名为“pn.txt”的文件,并将当前数字输出到“cn.txt”(这是为了让我知道它的限制是什么):
(@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
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
示例调用:isprime.cmd 2
会给你2 is prime!
.
请原谅我打了一匹死马。这是一种完全不同的纯批处理生成素数的方法,它优于我发现的所有其他方法。
它基于在我们正在检查的窗口周围保留先前找到的素数的倍数的列表。列表中未找到的数字是素数。为了保留列表,我使用 @composite=next_increment 形式的环境变量。它使用单循环,比其他算法中使用的嵌套双循环快得多,降级速度也慢。不幸的是,需要 FOR 和辅助 subrputine 来克服在环境中重复键的可能性,因为有时多个不同的素数会发生冲突。
顺便说一句,这个想法来自 Knuth 的 TAOCP 第 3 卷第 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
如果有的话,这也将告诉主要因素。