在批处理脚本中执行模数运算

Posted

技术标签:

【中文标题】在批处理脚本中执行模数运算【英文标题】:Performing Modulus Arithmetic Within a Batch Script 【发布时间】:2016-12-07 11:52:36 【问题描述】:

作为新事物,我正在尝试使用批处理脚本 (https://projecteuler.net/problem=5) 完成 Project Euler 问题 5。然而;我遇到了一些问题。如果有人可以检查我的代码,那就太好了。

@ECHO off

SET init=1
SET iter=1
SET /a func=%init% %% %iter%
cls

:Num
IF func==0 (
    IF iter==20 (
        ECHO Val = %init%
        pause
        exit
    ) ELSE (
        SET /a iter+=1
        GOTO Num
    )
) ELSE (
    SET iter=1
    SET /a init+=1
    GOTO Num
)

它的意思是检查init mod iter是否返回0,如果是,则将iter的值加1,直到达到21。但是;如果不等于 0,则迭代计数将设置回 0 并重新开始计算。


将要发生的事情的一个例子:
1 mod 1 = 0, Therefor add 1 to iter
1 mod 2 != 0, Therefor init is set to 0 and 1 is added to init
2 mod 1 = 0, Therefor add 1 to iter
2 mod 2 = 0, Therefor add 1 to iter
2 mod 3 != 0, Therefor init is set to 0 and 1 is added to init

等等等等。


发生了什么的一个例子:
1 mod 1 != 0, Therefor add 1 to init
2 mod 1 != 0, Therefor add 1 to init
3 mod 1 != 0, Therefor add 1 to init

等等等等。


任何帮助表示赞赏,谢谢。

【问题讨论】:

不过,我对代码做了一些更改;现在它完全跳过了模运算并说 1 mod 1 到 20 = 0。关于为什么这样做的想法? @ECHO off SET init=1 SET iter=1 SET /a func="%init% %% %iter%" cls :Num IF "%func%" == "0" ( IF "%iter%" == "21" ( echo. ECHO Val = %init% echo. echo Press any key to exit . . . pause > nul exit ) ELSE ( echo %init% mod %iter% = 0; CONT SET /a iter+=1 GOTO Num ) ) ELSE ( echo %init% mod %iter% != 0; BREAK SET iter=1 SET /a init+=1 GOTO Num ) 很抱歉格式不好。 你永远不会重新计算%func% 我该如何合并这个? :Num移动到SET /a func=%init% %% %iter%的正上方 你的蛮力方法不实用。假设您制定了正确的语法和逻辑,我相信这种方法需要很多天,也许很多周才能完成。即使您优化代码以使用 FOR /L 循环而不是相对较慢的 GOTO,我相信也需要很多小时才能完成,可能超过一天。 【参考方案1】:

这个怎么样:

@Echo off
setlocal enabledelayedexpansion
SET init=1 
SET iter=1 
cls 
set loopCounter=1
set loopBatch=1

:numLoop
SET /a func="!init! %% !iter!" 
IF !iter! == 21 (goto :done)
IF !func! == 0 (call :incIter) ELSE ( call :incInit)
SET /a loopCounter+=1 
SET /a loopBatch="%loopCounter% %% 1000" 
if !loopBatch! == 0 (echo %loopCounter% iterations done)
goto :numLoop

:incInit
  rem echo %init% mod %iter% == %func%; Increasing init
  SET iter=1 
  SET /a init+=1 
  goto :eof

:incIter
  rem echo %init% mod %iter% == %func%; Increasing iter
  SET /a iter+=1 
  goto :eof

:done
  echo. 
  ECHO Val = %init% 

【讨论】:

【参考方案2】:

只是发布一个“实用”(!?)解决方案,以防万一有人发现它“有用”(!!?)

@echo off
    setlocal enableextensions enabledelayedexpansion

    rem Our search limit 
    set "limit=20"
    rem Note: batch arithmetic is limited to 2^31 values, so 26 is the highest
    rem       value that we can directly use

    rem Initialize searched number
    set "euler5=1"

    rem Initialize list of numbers for a Erastotenes cribe
    for /l %%a in (2 1 %limit%) do set "f.%%a=%%a"

    rem Search for prime numbers and simplify (divide) greater multiples
    rem Keep multiplying as we iterate over the list 
    for /l %%a in (2 1 %limit%) do (
        if !f.%%a! gtr 1 (
            set /a "euler5*=!f.%%a!"
            for %%c in (!f.%%a!) do for /l %%b in (%%a %%a %limit%) do (
                set /a "f.%%b/=%%c"
            )
        )
    )

    rem Echo solution
    echo %euler5%

【讨论】:

【参考方案3】:

根据此链接:link 有一个模运算符。

所以你可以试试这个

@echo off

::we should start with 21 because we know that all numbers from 1-20
::cannot be divided by 20 all 20 times.
::This will also fix the problem of an unwanted a zero remainder at the
::early numbers

set count=21
set divide=1
::We need to set enabledelayedexpansion so we can use ! as a varible 
::expander.
setlocal enabledelayedexpansion

:loop
:: begin the modulus operator.
set /a remainder=!count!%%!divide!
if %remainder%==0 (
if %divide%==20
::Yea!
echo number found:%count%
::Don't forget to pause
::or else you cant see the number.
pause
) else (
set /a divide=%divide%+1
::equivelent to set /a divide+=1
goto :loop
)
) else (
set /a count=%count%+1
goto :loop
)

虽然这不能修复您的脚本,但它绝对是一种更快的方法。

【讨论】:

以上是关于在批处理脚本中执行模数运算的主要内容,如果未能解决你的问题,请参考以下文章

脚本分几种,用途都是啥?

Shell脚本处理浮点数的运算和比较实例

如何在文件夹和子文件夹中执行批处理文件执行脚本?

使用 sqlplus 命令在批处理文件中执行 sql 脚本

脚本是啥,用啥语言编写

windows 批处理脚本怎么执行