1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

A high-precision pi calculator that uses entirely batch commands.

Discussion in 'CMD' started by Joe Caverly, Sep 11, 2017.

  1. Joe Caverly

    Joined:
    Aug 28, 2009
    Messages:
    698
    Likes Received:
    8
    I found this example, which does not work with TCC, but works with CMD.
    Code:
    @if defined talk (echo on) else (echo off)
    setlocal EnableDelayedExpansion
    echo.pi.bat  -  By Don Cross  -  http://cosinekitty.com
    set /a NumQuads = 30
    set /a MaxQuadIndex = NumQuads - 1
    
    echo.
    echo.%time% - started
    echo.
    
    call :PiEngine 48 18 32 57 -20 239
    call :PiEngine 16 5 -4 239
    goto :EOF
    
    :PiEngine
        call :SetToInteger Pi 0
        set Formula=
        :PiTermLoop
            if "%1" == "" (
                call :Print pi
                echo.
                echo.!time! - finished !Formula!
                echo.
                goto :EOF
            )
            call :ArctanRecip PiTerm %2
            set /a PiEngineFactor=%1
            if !PiEngineFactor! lss 0 (
                set /a PiEngineFactor *= -1
                set Formula=!Formula!
                call :MultiplyByInteger PiTerm !PiEngineFactor!
                call :Subtract Pi PiTerm
                set Operator=-
            ) else (
                call :MultiplyByInteger PiTerm %1
                call :Add Pi PiTerm
                set Operator=+
            )
            if defined Formula (
                set Formula=!Formula! !Operator! !PiEngineFactor!*arctan^(1/%2^)
            ) else (
                set Formula=pi = %1*arctan^(1/%2^)
            )
            shift
            shift
        goto PiTermLoop
        
    :SetToInteger
        for /L %%i in (0, 1, !MaxQuadIndex!) do (
            set /a %1_%%i = 0
        )
        set /a %1_!MaxQuadIndex! = %2
        goto :EOF
        
    :Print
        set PrintBuffer=x
        REM  Omit a couple of least significant quads, because they will have roundoff errors.
        if defined PiDebug (
            set /a PrintMinQuadIndex=0
        ) else (
            set /a PrintMinQuadIndex=2
        )
        set /a PrintMaxQuadIndex = MaxQuadIndex - 1
        for /L %%i in (!PrintMinQuadIndex!, 1, !PrintMaxQuadIndex!) do (
            set PrintDigit=!%1_%%i!
            if !PrintDigit! lss 1000 (
                if !PrintDigit! lss 100 (
                    if !PrintDigit! lss 10 (
                        set PrintDigit=000!PrintDigit!
                    ) else (
                        set PrintDigit=00!PrintDigit!
                    )
                ) else (
                    set PrintDigit=0!PrintDigit!
                )
            )
            set PrintBuffer=!PrintDigit!!PrintBuffer!
        )
        set PrintBuffer=!%1_%MaxQuadIndex%!.!PrintBuffer:x=!
        echo.%1 = !PrintBuffer!
        goto :EOF
        
    :DivideByInteger
        if defined PiDebug echo.DivideByInteger %1 %2
        set /a DBI_Carry = 0
        for /L %%i in (!MaxQuadIndex!, -1, 0) do (
            set /a DBI_Digit = DBI_Carry*10000 + %1_%%i
            set /a DBI_Carry = DBI_Digit %% %2
            set /a %1_%%i = DBI_Digit / %2
        )
        goto :EOF
        
    :MultiplyByInteger
        if defined PiDebug echo.MultiplyByInteger %1 %2
        set /a MBI_Carry = 0
        for /L %%i in (0, 1, !MaxQuadIndex!) do (
            set /a MBI_Digit = %1_%%i * %2 + MBI_Carry
            set /a %1_%%i = MBI_Digit %% 10000
            set /a MBI_Carry = MBI_Digit / 10000
        )
        goto :EOF   
        
    :ArctanRecip
        if defined PiDebug echo.ArctanRecip %1 %2
        call :SetToInteger %1 1
        call :DivideByInteger %1 %2
        call :CopyValue AR_Recip %1
        set /a AR_Toggle = -1   
        set /a AR_K = 3
        :ArctanLoop
            if defined PiDebug (
                echo.
                echo.ArctanRecip  AR_K=!AR_K!    ---------------------------------------------------------
            )
            call :DivideByInteger AR_Recip %2
            call :DivideByInteger AR_Recip %2
            call :CopyValue AR_Term AR_Recip
            call :DivideByInteger AR_Term !AR_K!
            call :CopyValue AR_PrevSum %1
            if !AR_Toggle! lss 0 (
                call :Subtract %1 AR_Term
            ) else (
                call :Add %1 AR_Term
            )
            call :Compare AR_EqualFlag %1 AR_PrevSum
            if !AR_EqualFlag! == true goto :EOF
            set /a AR_K += 2
            set /a AR_Toggle *= -1
        goto ArctanLoop
        
    :CopyValue
        if defined PiDebug echo.CopyValue %1 %2
        for /L %%i in (0, 1, !MaxQuadIndex!) do (
            set /a %1_%%i = %2_%%i
        )
        goto :EOF
        
    :Add
        if defined PiDebug echo.Add %1 %2
        if defined PiDebug call :Print %1
        if defined PiDebug call :Print %2
        set /a Add_Carry = 0
        for /L %%i in (0, 1, !MaxQuadIndex!) do (
            set /a Add_Digit = Add_Carry + %1_%%i + %2_%%i
            set /a %1_%%i = Add_Digit %% 10000
            set /a Add_Carry = Add_Digit / 10000
        )
        goto :EOF   
    
    :Subtract
        if defined PiDebug echo.Subtract %1 %2
        if defined PiDebug call :Print %1
        if defined PiDebug call :Print %2
        set /a Subtract_Borrow = 0
        for /L %%i in (0, 1, !MaxQuadIndex!) do (
            set /a Subtract_Digit = %1_%%i - %2_%%i - Subtract_Borrow
            if !Subtract_Digit! lss 0 (
                set /a Subtract_Digit += 10000
                set /a Subtract_Borrow = 1
            ) else (
                set /a Subtract_Borrow = 0
            )
            set /a %1_%%i = Subtract_Digit
        )
        goto :EOF   
        
    :Compare
        if defined PiDebug echo.Compare %1 %2 %3
        if defined PiDebug call :Print %2
        if defined PiDebug call :Print %3
        set /a Compare_Index = 0
        set %1=true
        :CompareLoop
            if not !%2_%Compare_Index%! == !%3_%Compare_Index%! (
                if defined PiDebug echo.!%2_%Compare_Index%! neq !%3_%Compare_Index%!
                set %1=false
                goto :EOF
            )
            set /a Compare_Index += 1
            if !Compare_Index! gtr !MaxQuadIndex! (
                if defined PiDebug echo.Compare equal
                goto :EOF
            )
        goto CompareLoop   
        
    REM    $Log: pi.bat,v $
    REM    Revision 1.2  2007/09/06 21:49:15  Don.Cross
    REM    Added time stamps and display of formula.
    REM
    REM    Revision 1.1  2007/09/06 21:12:36  Don.Cross
    REM    Batch file for calculating pi
    REM
    
    Joe
     
  2. samintz

    samintz Scott Mintz

    Joined:
    May 20, 2008
    Messages:
    1,201
    Likes Received:
    11
    I also noticed that when I run this under TCC/Tcmd, that neither Ctrl+C nor Ctrl+Break actually stop execution of the script.

    I have to hit Ctrl+Break multiple times to interrupt the script and stop it.
     
  3. K_Meinhard

    Joined:
    May 20, 2008
    Messages:
    312
    Likes Received:
    0
    Under TCMD, Ctrl-C works fine. Not so under CMD, however. Strange.

    Under both, the batch produces a divide-by-zero error here.
     
  4. Joe Caverly

    Joined:
    Aug 28, 2009
    Messages:
    698
    Likes Received:
    8
    On my Windows 7 x64 system, running CMD.EXE 64-bit or CMD.EXE 32-bit, this is what I get;
    Code:
    c:\utils>pi.cmd
    pi.bat  -  By Don Cross  -  http://cosinekitty.com
    
    17:37:37.85 - started
    
    pi = 3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086
    
    17:37:41.25 - finished pi = 48*arctan(1/18) + 32*arctan(1/57) - 20*arctan(1/239)
    
    pi = 3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086
    
    17:37:44.75 - finished pi = 16*arctan(1/5) - 4*arctan(1/239)
    TCC 18.00.32 x64 returns;
    Code:
    c:\users\jlc\utils>pi.cmd
    pi.bat  -  By Don Cross  -  http://cosinekitty.com
    
    17:39:58.88 - started
    
    MAPM Warning: 'M_apm_sdivide', Divide by 0
    TCC: C:\Users\jlc\utils\pi.cmd [90]  Divide by zero " DBI_Digit /"
    TCC-RT 21.01.49 x64 returns;
    Code:
    c:\users\jlc\utils>"C:\Program Files\JPSoft\TCC_RT_21\tcc.exe" /I /Q /C pi.cmd
    pi.bat  -  By Don Cross  -  http://cosinekitty.com
    
    17:41:28.66 - started
    
    TCC: C:\Users\jlc\utils\pi.cmd [90]  Divide by zero " DBI_Digit %"
    TCC: C:\Users\jlc\utils\pi.cmd [90]  Divide by zero " DBI_Digit /"
    Joe
     
  5. rconn

    rconn Administrator
    Staff Member

    Joined:
    May 14, 2008
    Messages:
    10,036
    Likes Received:
    84
    I am impressed that the author was able to beat CMD into producing these results. And saddened that he wasted days of his life doing it.

    The same result of his 195-line CMD batch file can be done in 1 line in TCC:

    echo pi = %@eval[pi=0.108]

    Or if you want a really high resolution pi:

    echo pi=%@eval[pi=0.10000]

    TCC calculating pi to 10,000 decimal places runs about 600 times faster than the CMD batch file calculating it to 108 places.

    And the reason the batch file doesn't run in TCC is because of invalid syntax in his SET /A statements. Which CMD is rewriting internally to the correct format, which is (1) undocumented, and (2) inconsistent with how it parses SET statements without the /A. But I have made a change for 21.01.50 to emulate this undocumented behavior. Who knows, it might even be a CMD "feature".
     

Share This Page