【问题标题】:How to find large factorials using a batch script如何使用批处理脚本查找大阶乘
【发布时间】:2014-01-09 12:46:27
【问题描述】:
@echo off
if %1.==. ( echo Missing parameter! Try passing the number as a parameter     like   'factorial   10' without the quotes.
goto end )
setlocal enabledelayedexpansion
set /a count=0
set /a temp=0
set /a digits=1
set /a array1=1
for /L %%i IN (2,1,%1) do (
set /a temp=0
for /L %%j IN ( 1,1,!digits! ) do (
set /a temp=!temp!+!array%%j!*%%i
set /a array%%j=!temp!%%10
set /a temp=!temp!/10   ) 

set /a index=!digits!+1

for /L %%v IN (!index!,1,!index! ) do (
if !temp! NEQ 0 (
set /a array!index!=!temp!%%10
set /a temp/=10
set /a index+=1 ))
set /a digits=!index!-1)
for /l %%v IN ( !digits!,-1,1 ) do set array=!array!!array%%v!
echo !array!
echo Total # of decimal digits = !digits!
:end
pause

这是我到目前为止所得到的。 10以下还算稳定!但是一旦我达到 15 或 20,它就会开始丢失一些数字。

我的编辑......

@echo off
if %1.==. ( echo Missing parameter! Try passing the number as a parameter  like   'factorial   10' without the quotes.
goto end )
setlocal enabledelayedexpansion
set /a count=0
set /a temp=0
set /a digits=1
set /a array1=1
for /L %%i IN (2,1,%1) do (
set /a temp=0
for /L %%j IN ( 1,1,!digits! ) do (
set /a temp=!temp!+!array%%j!*%%i
set /a array%%j=!temp!%%10
set /a temp=!temp!/10   ) 

for /l %%v IN ( 1,1,30 ) do (
if !temp! neq 0 (
set /a digits+=1
set /a array!digits!=!temp!%%10
set /a temp=!temp!/10
)))
for /l %%v IN ( !digits!,-1,1 ) do set array=!array!!array%%v!
echo !array!
echo Total # of decimal digits = !digits!
:end
pause

现在我强制最后一个内部循环运行 30 次,尽管在此之前温度可能为零。有没有办法编写类似于以下c代码的sn-p 而(温度) {/代码放在这里/}

只有当 temp 不为零时才会执行。

对于一个批次中变量的大小是否有任何特殊限制? 我知道批量调试计算程序很痛苦*,我只是想用我知道的所有编程语言对此进行编码,这样我就可以比较它们的速度。有人可以指出我在这里做错了什么。

编辑........22/12/13

@echo off
if %1.==. ( echo Missing parameter! Try passing the number as a parameter like   'factorial   10' without the quotes.
goto end )
setlocal enabledelayedexpansion

set /a count=0
set /a tempo=0
set /a digits=1
set /a array1=1

for /f "tokens=1-4 delims=:.," %%a IN ("%time%") do (     
set /a "start=(((%%a*60)+1%%b %% 100)*60+1%%c %%100)*100+1%%d %% 100"
)

for /L %%i IN (2,1,%1) do (
set /a tempo=0
for /L %%j IN ( 1,1,!digits! ) do (
set /a tempo=!tempo!+!array%%j!*%%i
set /a array%%j=!tempo!%%10000
set /a tempo=!tempo!/10000   ) 

for /l %%v IN (1,1,2) do (
if !tempo! neq 0 (
set /a digits+=1
    set /a array!digits!=tempo%%10000
set /a tempo=tempo/10000
))
)

for /l %%v IN ( !digits!,-1,1 ) do set array=!array!!array%%v!
echo !array!  
echo Total # of decimal digits = !digits!

for /f "tokens=1-4 delims=:.," %%a in ("%time%") do (
set /a "end=(((%%a*60)+1%%b %% 100)*60+1%%c %%100)*100+1%%d %% 100"
)

set /a elapsedcs=end-start
set /a elapseds=elapsedcs/100
set /a elapsedcs=elapsedcs%%100
echo %elapseds%.%elapsedcs% seconds
:end
rem label should never be the last statement

这就是你的意思 aacini 吗?

【问题讨论】:

    标签: batch-file factorial


    【解决方案1】:

    为了在 Batch 中实现对 Big numbers 的快速算术运算,您必须将 Bignum 拆分为 数字组,这些数字组可以通过 set /A 命令的 32 位运算进行管理。最大的 32 位有符号整数是 2147483647,所以这种方式可以相乘的最大数字组是 4,因为 5 位数字(99999 x 99999)超过了最大数字。加法和乘法必须从右到左实现,将“进位”翻译到左边的下一组。减法和除法必须从左到右实现,将“借”到右边的下一组。下面的批处理文件使用这种方法将一个Bignum 连续乘以一个4 位数的因子,所以它最多可以计算出9999!只要包含 4 位数字组的所有变量都适合环境的64 MB size limit(在“设置环境变量”下查找“65,536KB 最大大小”)。结果直接输出到屏幕,避免了一个Batch变量的8192位限制。

    编辑:我稍微修改了程序以便运行得更快并得到结果中的位数。

    @echo off
    
    if "%1" equ "" (
       echo Missing parameter! Try passing the number as a parameter like 'factorial 10' without the quotes.
       goto end
    )
    
    setlocal EnableDelayedExpansion
    
    rem Calculate the factorial
    set /A g1=1, groups=1
    for /L %%n in (2,1,%1) do (
       set carry=0
       for /L %%g in (1,1,!groups!) do (
          set /A group=g%%g*%%n+carry, g%%g=group%%10000, carry=group/10000
       )
       if !carry! neq 0 (
          set /A groups+=1
          set g!groups!=!carry!
       )
    )
    
    rem Show the factorial
    set /P "=!g%groups%!" < NUL
    set /A groupsM1=groups-1
    for /L %%g in (%groupsM1%,-1,1) do (
       set group=000!g%%g!
       set /P "=!group:~-4!" < NUL
    )
    echo/
    
    rem Get the number of digits
    set digits=0
    for /L %%i in (0,1,3) do if "!g%groups%:~%%i,1!" neq "" set /A digits+=1
    set /A digits+=4*groupsM1
    echo Total # of decimal digits = %digits%
    
    :end
    pause
    

    【讨论】:

    • 老兄请看看我的编辑。我真的不明白经过时间功能是如何工作的,我只是从论坛复制粘贴它。你能解释一下吗。我知道 for loop with /f swithch 如何使用分隔符工作。但为什么它是 1%%b %% 100 而不仅仅是 %%b
    • 还有一件事我是新来的堆栈溢出(你可以从我赢得的声誉中理解)。有没有办法发布代码而不是复制粘贴整个内容然后在每行的开头缩进 4 个空格。
    • @krish: 1. 是为了消除被set /A 视为八进制数的左零,所以09 会报错。这样1%%b 将给出109,而1%%b %% 100 给出109 的余数除以100 = 9。 2.首先选择需要的代码,然后点击编辑窗口上方的大括号{}
    • 非常感谢,我终于开始明白了。还有一件事,your answer 我读了你对时间过去的回答,我明白了,感谢你。但是在 Gynnad 的回答中,他使用了 1%STARTTIME:~0,2%-100) 这是什么?
    【解决方案2】:

    我不得不重新阅读代码以查看它在做什么。好的。

    您的代码必须面对三个限制。

    1 - 在内部 %%j%%v 循环中,buffer 用于乘以 %%i 中的当前值,您面临 Magoo 指示的限制。您不能使用大于 2^31 的值对 set /a 进行操作。由于array 中的值限制为 0-9,这意味着此限制将不允许您计算大于 214748364(近似值)的数字的阶乘

    2 - 环境变量的大小有限制。它不能容纳超过 32767 个字符。当您连接要输出到控制台的数字时(下一个限制是相关的),这会将您限制为低于 9273(aprox)的数字的阶乘。

    3 - cmd 可以处理的行的长度有限制。它是 8191 个字符。这不限制你的计算,但你不能使用在变量中连接的方法来表示数字。如果方法未更改,这会将您限制为小于 2727(近似值)的数字的阶乘。

    【讨论】:

      【解决方案3】:

      批处理仅限于有符号的 32 位整数。

      顺便说一句 - 不要使用 temptmp 作为用户变量。它由系统设置为指向存储临时文件的目录的指针。

      【讨论】:

      • 谢谢男人应该想到的。!谢谢你可以改进我的编辑。
      • 伙计,这不是我要求的 int 的大小是否有一个字符串可以存储在环境变量中的大小的限制。在我的代码中,我已将所有数组元素连接到一个新的变量数组。请看一下。
      猜你喜欢
      • 2022-07-02
      • 1970-01-01
      • 1970-01-01
      • 2021-12-26
      • 2011-06-15
      • 1970-01-01
      • 1970-01-01
      • 2013-07-30
      • 2016-07-16
      相关资源
      最近更新 更多