I was scanning the final v0.2 macro and cleaning up the various versions I went through over the last couple of months (about 12) and think that, other than any corrections for discovered errors, %MM% is done. It might be possible to squeeze out a few dozen more characters, but what else is there?

The idea of inserting strings into error messages has merit. There are 9 ECHOs where errors occur, any of the variables listed in the comments could be included with the error to help illustrate what went wrong. This is originally how I planned the errors messages, but because of size constraint and my desire to have it appear just like SET/A I removed them. Other than that, I think bugfix will be the only other release.

Oh, thanks Dave for archiving v0.1 on the second post of this thread. In my zeal to post v0.2 I simply clobbered on top of it.^_^

Just for grins, I thought I'd post an early version of MM, from when I though I was just writing a quick integer-only macro to add and divide large cumulative file sizes. This is the 4th version I have saved named iMath2.cmd. I didn't change a thing, so the code may be a bit messy:

Code: Select all

```
:: %iMath% [var=] num|var +|-|x|/|@|GT|LS|EQ|GE|LE|NE num|var [;...]
:: Macro for mathmatical and comparison operations of large integers.
:: Operands containing only -0123456789. are input as integers, else variables.
:: Decimals are truncated and undefined variables are treated as zero.
:: The value of each operation is always returned in variable %iMath_%.
:: Comparison operations will also return ERRORLEVEL 0=false, 1=true.
:: Multiple expressions may be separated by comma[,] or semicolon[;] and
:: spaces must separate all operands from operators other than [=,;].
:: Variable names beginning with 'iMath*' are reserved and should not be used.
:: SET mx=maximum # of digits up to ~256, larger numbers=slower runtimes.
:: Divisor for / and @ is limited to 8 digits, the dividend has no such limit.
::
:: add +: %iMath% 123456789 + 987654321;sets iMath_=1111111110, always
:: subtract -: %iMath% var1=9876543210 - -1234567890;sets var1=1111111110
:: multiply x: %iMath% var2=777.777 x var1;truncate decimal, var2=863333332470
:: divide /: %iMath% var3=var2 / 777.0123456789;divides var2 by 777
:: modulus @: %iMath% var4=var1 @ var3;sets var4=0 as var1=var3=1111111110
:: comparison: %iMath% var4=var1 EQU var3;sets both var4 and ERRORLEVEL = 1
::
@SET mx=16
@ECHO OFF
SETLOCAL EnableExtensions EnableDelayedExpansion
:: make zeros for padding
SET z0=0000000000000000
FOR %%A IN (1 2 3) DO CALL SET z0=%%z0%%%%z0%%%%z0%%%%z0%%
CALL SET z0=%%z0:~-%mx%%%
:: setup macro constants
SET ^"LF=^
^"
SET ^"\n=^^^%LF%%LF%^%LF%%LF%^^"
IF "!!"=="" ( SET "b=^^^^^^^!" & SET "q=^^^!"
) ELSE SET "b=!" & SET "q=!"
SET iMath=FOR %%# IN (1 2) DO IF %%#==2 ( SETLOCAL EnableExtensions EnableDelayedExpansion%\n%
FOR %%A IN (C E0 E1 N0 N1 N2 OP R U0 U1 U2 V) DO SET iMath%%A=%\n%
SET "iMathH=[var=] num|var +|-|x|/|@|GT|LS|EQ|GE|LE|NE num|var [;...]"%\n%
IF NOT DEFINED iMathP SET iMathP=A%\n%
SET iMathP=%b%iMathP:^"=%b%%\n%
SET iMathP=%b%iMathP:\=/%b%%\n%
SET iMathP=%b%iMathP:,=;%b%%\n%
SET iMathP=%b%iMathP:;=^" ^"%b%%\n%
FOR /F "tokens=1* delims=*" %%A IN ("%q%iMathP%q%") DO IF "%%B" NEQ "" SET iMathP=^& SET iMathE1= 00^& ECHO unknown operator *: %b%iMathH%b%^>^&2%\n%
FOR %%: IN ("%q%iMathP%q%") DO IF %%: NEQ "" ( SETLOCAL%\n%
SET iMathT=%%~:%\n%
FOR /F "tokens=1* delims==" %%A IN (%%:) DO IF "%%B" NEQ "" FOR %%C IN (%%A) DO SET iMathV=%%C^& SET iMathT=%%B%\n%
FOR /F "tokens=1-3" %%A IN ("%q%iMathT%q%") DO SET iMathOP=%%B^& SET iMathT=%%A %%C%\n%
FOR %%A IN (%b%iMathT%b%) DO FOR /F "tokens=* delims=-0123456789." %%B IN ("%%A") DO ( SET /A iMathC+=1%\n%
IF "%%B"=="" ( SET iMathT=%%A%\n%
) ELSE SET iMathT=%b%%%A%b%%\n%
IF NOT DEFINED iMathT SET iMathT=0%\n%
IF "%q%iMathT:~0,1%q%"=="-" SET iMathT=%b%iMathT:~1%b%^& SET iMathU%b%iMathC%b%=-%\n%
FOR /F "tokens=1 delims=." %%C IN ("%q%iMathT%q%.") DO SET iMathN%b%iMathC%b%=%z0%%%C)%\n%
SET /A f0=t0=t1=t2=t3=0%\n%
FOR %%A IN (e0 n0 n1 n2 op u0 u1 u2) DO SET %%A=%b%iMath%%A%b%%\n%
IF "%q%op%q%"=="+" IF "%q%u2%q%" NEQ "%q%u1%q%" SET u2=%b%u1%b%^& SET op=-%\n%
IF "%q%op%q%"=="-" IF "%q%u2%q%" NEQ "%q%u1%q%" SET u2=%b%u1%b%^& SET op=+%\n%
IF "%q%op%q%"=="@" SET op=/^& SET f0=1%\n%
IF %b%iMathC%b% LSS 2 ( SET e0= 00%\n%
ECHO missing parameters: %b%iMathH%b%^>^&2%\n%
) ELSE IF "%q%op%q%"=="+" ( SET u0=%b%u1%b%%\n%
FOR /L %%A IN (1,1,%mx%) DO ( SET /A t1=%b%n1:~-%%A,1%b%+%b%n2:~-%%A,1%b%+t0,t0=0%\n%
IF %b%t1%b% GTR 9 SET /A t1-=10,t0=1%\n%
SET n0=%b%t1%b%%b%n0%b%)%\n%
) ELSE IF "%q%op%q%"=="-" (%\n%
FOR /L %%A IN (1,1,%mx%) DO ( SET /A t1=%b%n1:~-%%A,1%b%,t2=%b%n2:~-%%A,1%b%%\n%
IF %b%t1%b% GTR %b%t2%b% SET t3=1%\n%
IF %b%t1%b% LSS %b%t2%b% SET t3=2)%\n%
IF %b%t3%b%==2 ( SET t1=%b%n1%b%^& SET n1=%b%n2%b%^& SET n2=%b%t1%b%%\n%
IF "%q%u1%q%"=="" SET u0=-%\n%
) ELSE SET u0=%b%u1%b%%\n%
IF %b%t3%b% NEQ 0 FOR /L %%A IN (1,1,%mx%) DO (%\n%
SET /A t1=%b%n1:~-%%A,1%b%,t2=%b%n2:~-%%A,1%b%+t0,t0=0%\n%
IF %b%t1%b% LSS %b%t2%b% SET /A t1+=10,t0=1%\n%
SET /A t1-=t2%\n%
SET n0=%b%t1%b%%b%n0%b%)%\n%
) ELSE IF /I "%q%op%q%"=="x" ( IF "%q%u1%q%" NEQ "%q%u2%q%" SET u0=-%\n%
FOR /L %%A IN (1,1,%mx%) DO SET _%%A=0%\n%
FOR /L %%A IN (1,1,%mx%) DO ( SET /A t0=0,c0=%%A%\n%
FOR /L %%B IN (1,1,%mx%) DO SET /A t1=%b%n1:~-%%A,1%b%*%b%n2:~-%%B,1%b%+t0,t0=t1/10,_%b%c0%b%+=t1 %% 10,c0+=1%\n%
SET _%b%c0%b%=%b%t0%b%)%\n%
FOR /L %%A IN (1,1,%b%c0%b%) DO (%\n%
SET /A _%%A+=t2,t2=_%%A/10%\n%
SET n0=%b%_%%A:~-1%b%%b%n0%b%)%\n%
SET n0=%b%t2%b%%b%n0%b%%\n%
) ELSE IF "%q%op%q%"=="/" ( IF "%q%u1%q%" NEQ "%q%u2%q%" SET u0=-%\n%
FOR %%A IN (1 2) DO ( FOR /F "tokens=* delims=0" %%B IN ("%q%n%%A%q%") DO SET n%%A=%%B%\n%
IF NOT DEFINED n%%A SET n%%A=0)%\n%
IF %b%n2%b%==1 ( SET n0=%b%n1%b%%\n%
) ELSE IF %b%n2%b%==0 ( SET e0= 00%\n%
ECHO Divide by zero error.^>^&2%\n%
) ELSE IF %b%n1%b% NEQ 0 FOR /L %%A IN (0,1,%mx%) DO IF "%q%n1:~%%A,1%q%" NEQ "" ( SET t1=0%\n%
IF %b%t0%b%==0 SET t0=%\n%
SET t0=%b%t0%b%%b%n1:~%%A,1%b%%\n%
IF %b%t0%b% GEQ %b%n2%b% FOR /L %%B IN (1,1,9) DO IF %b%t0%b% GEQ %b%n2%b% SET /A t1+=1,t0-=n2%\n%
SET n0=%b%n0%b%%b%t1%b%)%\n%
IF %b%f0%b% NEQ 0 SET u0=%b%u1%b%^& SET n0=%b%t0%b%%\n%
) ELSE ( SET /A n0=0,gt=1,lt=-1%\n%
IF "%q%u1%q%"=="" IF "%q%u2%q%"=="-" SET t0=1%\n%
IF "%q%u1%q%"=="-" IF "%q%u2%q%"=="" SET t0=-1%\n%
IF "%q%u1%q%"=="-" IF "%q%u2%q%"=="-" SET /A gt=-1,lt=1%\n%
IF %b%t0%b%==0 FOR /L %%A IN (1,1,%mx%) DO ( SET /A t1=%b%n1:~-%%A,1%b%,t2=%b%n2:~-%%A,1%b%%\n%
IF %b%t1%b% GTR %b%t2%b% SET t0=%b%gt%b%%\n%
IF %b%t1%b% LSS %b%t2%b% SET t0=%b%lt%b%)%\n%
IF /I "%q%op:~0,2%q%"=="GT" ( IF %b%t0%b% GTR 0 SET n0=1%\n%
) ELSE IF /I "%q%op:~0,2%q%"=="LS" ( IF %b%t0%b% LSS 0 SET n0=1%\n%
) ELSE IF /I "%q%op:~0,2%q%"=="EQ" ( IF %b%t0%b% EQU 0 SET n0=1%\n%
) ELSE IF /I "%q%op:~0,2%q%"=="GE" ( IF %b%t0%b% GEQ 0 SET n0=1%\n%
) ELSE IF /I "%q%op:~0,2%q%"=="LE" ( IF %b%t0%b% LEQ 0 SET n0=1%\n%
) ELSE IF /I "%q%op:~0,2%q%"=="NE" ( IF %b%t0%b% NEQ 0 SET n0=1%\n%
) ELSE SET e0= 00^& ECHO unknown operator %b%op:~0,2%b%: %b%iMathH%b%^>^&2%\n%
IF %b%n0%b%==1 SET e0= 00)%\n%
FOR /F "tokens=* delims=0" %%A IN ("%q%n0%q%") DO SET n0=%%A%\n%
IF NOT DEFINED n0 SET n0=0%\n%
IF %b%n0%b% NEQ 0 SET n0=%b%u0%b%%b%n0%b%%\n%
FOR /F "tokens=1-3 delims=;" %%A IN (^""%q%iMathV%q%";"%q%n0%q%";"%q%e0%q%"^") DO (%\n%
ENDLOCAL%\n%
IF %%A NEQ "" SET %%~A=%%~B^& SET iMathR=%b%iMathR%b%" "%%~A=%%~B%\n%
SET iMath_=%%~B%\n%
SET iMathE1=%%~C))%\n%
FOR /F "tokens=1-3 delims=;" %%A IN (^""%q%iMathR%q%";"%q%iMath_%q%";"COLOR%q%iMathE1%q%"^") DO (%\n%
ENDLOCAL%\n%
FOR %%: IN (%%A) DO IF %%: NEQ "" SET %%:%\n%
SET iMath_=%%~B%\n%
%%~C)%\n%
) ELSE SET iMathP=
GOTO :m2
:m1
SET xx=Q
SET/P xx=
IF /I "%xx%" NEQ "Q" (
%iMath% %xx%
IF ERRORLEVEL 1 ( ECHO Yup ) ELSE ( ECHO Nerp )
CALL ECHO %%iMath_%% : %%ERRORLEVEL%%
GOTO :m1
) ELSE SET
IF "!!"=="" ENDLOCAL
EXIT /B 0
:m2
SET rn1=%RANDOM%
SET rn2=%RANDOM%
SET rn3=7%rn1%%RANDOM%
SET rn4=4%rn2%%RANDOM%
ECHO %rn3:~0,9% : %rn4:~0,9%
SET /A x1=%rn3:~0,9% + %rn4:~0,9%
%iMath% x2=%rn3:~0,9% + %rn4:~0,9%
ECHO.%x1% : %x2%
IF "%x1%" NEQ "%x2%" EXIT /B 0
SET /A x1=%rn3:~0,9% - %rn4:~0,9%
%iMath% x2=%rn3:~0,9% - %rn4:~0,9%
ECHO.%x1% : %x2%
IF "%x1%" NEQ "%x2%" EXIT /B 0
SET /A x1=%rn3:~0,6% * %rn4:~0,3%
%iMath% x2=%rn3:~0,6% x %rn4:~0,3%
ECHO.%x1% : %x2%
IF "%x1%" NEQ "%x2%" EXIT /B 0
SET /A x1=%rn3:~0,9% / %rn4:~0,8%
%iMath% x2=%rn3:~0,9% / %rn4:~0,8%
ECHO.%x1% : %x2%
IF "%x1%" NEQ "%x2%" EXIT /B 0
SET /A x1=%rn3:~0,9% %% %rn4:~0,8%
%iMath% x2=%rn3:~0,9% @ %rn4:~0,8%
ECHO.%x1% : %x2%
IF "%x1%" NEQ "%x2%" EXIT /B 0
GOTO :m2
EXIT /B 0
```

It's the last version before I added the parser and it's

*much* faster without the decimal+shunting-yard overhead. Just thought I'd post it as a curiosity before I eventually delete the earlier versions.