Code: Select all

```
:Rand x result
set /A %2=%1 * %random% / 32768 + 1
exit /B
```

Code: Select all

```
call :Rand 25 num
echo Random number between 1 and 25: %num%
```

Code: Select all

```
set "Rand(x)=x * ^!random^! / 32768 + 1"
```

Code: Select all

```
set /A num=%Rand(x):x=25%
echo Random number between 1 and 25: %num%
```

Code: Select all

```
set "Rand(x)=( (x)*^!random^!/32768+1 )"
set /A num=%Rand(x):x=5*6% + 10
echo Random number between 11 and 40: %num%
```

Code: Select all

```
set "Sign(x)=((x)>>31|1)"
set "Abs(x)=(((x)>>31|1)*(x))"
```

Code: Select all

```
set "Abs(x)=(a=(x), (a>>31|1)*a)
```

In the manipulation of the 0 and 1 values returned by conditions the multiplication may work as AND boolean operator, addition may work as OR, and exclamation-mark works as NOT. The expression "!!value" is 0 if "value" is 0 and is 1 otherwise, so it may be used to reduce several values accumulated by addition operator (OR) into a single 1. You may also use "&", "|" and "^" bitwise operators for AND, OR and XOR boolean operators, respectively, that directly gives proper results when the values are 0 or 1.

The Max function below get the maximum of two values. We can use one parameter only, so we need to place the other value in a variable:

Code: Select all

```
REM Max1(x)= if (x geq y) then x else y
set "Max1(x)=( ?=((x-y)>>31)+1, ?*x + ^^^!?*y )"
set /P "pair=Enter two numbers separated by space: "
for /F "tokens=1,2" %%a in ("%pair%") do set /A "a=%%a, b=%%b"
set /A "y=b, max=%Max1(x):x=a%" // or: set /A "max=(y=b, %Max1(x):x=a%)"
echo The max is: %max%
```

In certain cases we can

*simulate*two arguments in a function if algebraic manipulations allows it; this depends on the specific formula used in the calculation. The function below is the Max function with two arguments:

Code: Select all

```
set "Max(x,y)=( ?=((x,y)>>31)+1, ?*(2*x,y-(x,y)) + ^^^!?*(x,y-(x,y*2)) )"
```

Code: Select all

```
set /A "max=%Max(x,y):x,y=one-two%"
echo The max of %one% and %two% is: %max%
```

*different variables*).

The conversion functions from HHMMSSCC time to centiseconds and viceversa are straightforward:

Code: Select all

```
set "HMSCtoCSec(HMSC)=( a=(HMSC), h=a/1000000, a%%=1000000, m=a/10000, a%%=10000, s=a/100, c=a%%100, ((h*60+m)*60+s)*100+c )"
set "CSecToHMSC(CSec)=( a=(CSec), c=a%%100, a/=100, s=a%%3600, a/=3600, m=a%%60, h=a/60, h*1000000+m*10000+s*100+c )"
echo %time% & for /F "tokens=1-4 delims=:." %%a in ("%time%") do set "startTime=%%a%%b%%c%%d"
place here any process
echo %time% & for /F "tokens=1-4 delims=:." %%a in ("%time%") do set "endTime=%%a%%b%%c%%d"
set /A "elapsed=%TimeToCSec(HMSC):HMSC=endTime% - %TimeToCSec(HMSC):HMSC=startTime%"
echo Elapsed time: %elapsed:~0,-2%.%elapsed:~-2% seconds
```

Code: Select all

```
set "DateToJDN(YMD)=( a=(YMD), y=a/10000, a%%=10000, m=a/100, d=a%%100, a=(m-14)/12, (1461*(y+4800+a))/4+(367*(m-2-12*a))/12-(3*((y+4900+a)/100))/4+d-32075 )"
set "JDNtoDate(JDN)=( a=(JDN), l=a+68569,n=(4*l)/146097,l=l-(146097*n+3)/4,i=(4000*(l+1))/1461001,l=l-(1461*i)/4+31,j=(80*l)/2447,d=l-(2447*j)/80,l=j/11,m=j+2-(12*l),y=100*(n-49)+i+l,y*10000+m*100+d )"
set /P "otherDate=Enter a date in YYYY/MM/DD format: "
for /F "tokens=1-3 delims=/" %%a in ("%date%") do set "today=%%c%%a%%b"
set /A "days=%DateToJDN(YMD):YMD=today% - %DateToJDN(YMD):YMD=!otherDate:/=!%"
echo/
echo There are %days% days between that date and today
```

Code: Select all

```
@echo off
setlocal EnableDelayedExpansion
rem Definition and use of arithmetic "functions" in Batch files
rem http://www.dostips.com/forum/viewtopic.php?f=3&t=6744
rem Antonio Perez Ayala
:: Define Rand(x) function
set "Rand(x)=x * ^!random^! / 32768 + 1"
:: Use Rand(x) function
set /A num=%Rand(x):x=25%
echo Random number between 1 and 25: %num%
:: Define Rand(x) to be used as a true function
set "Rand(x)=( (x)*!random!/32768+1 )"
set /A num=%Rand(x):x=5*6% + 10
echo Random number between 11 and 40: %num%
:: Define Max1(x) function with one parameter and one variable
REM Max1(x)= if (x geq y) then x else y
set "Max1(x)=( ?=((x-y)>>31)+1, ?*x + ^^^!?*y )"
echo/
echo Max1(x) function test
:nextPair1
set "pair="
set /P "pair=Enter two numbers separated by space: "
if not defined pair goto endPair1
for /F "tokens=1,2" %%a in ("%pair%") do set /A "a=%%a, b=%%b"
set /A "max=(y=b, %Max1(x):x=a%)"
echo The max is: %max%
goto nextPair1
:endPair1
:: Define Max(x,y) and Min(x,y) functions with two parameters
set "Max(x,y)=( ?=((x,y)>>31)+1, ?*(2*x,y-(x,y)) + ^^^!?*(x,y-(x,y*2)) )"
set "Min(x,y)=( ?=((x,y)>>31)+1, ?*(x,y-(x,y*2)) + ^^^!?*(2*x,y-(x,y)) )"
echo/
echo Max(x,y) function test
:nextPair
set "pair="
set /P "pair=Enter two numbers separated by space: "
if not defined pair goto endPair
for /F "tokens=1,2" %%a in ("%pair%") do set /A "a=%%a, b=%%b"
set /A "max=%Max(x,y):x,y=a-b%"
echo The max is: %max%
goto nextPair
:endPair
:: Define HHMMSSCC time to centiseconds conversion function and viceversa
set "TimeToCSec(HMSC)=( a=(HMSC), h=a/1000000, a%%=1000000, m=a/10000, a%%=10000, s=a/100, c=a%%100, ((h*60+m)*60+s)*100+c )"
set "CSecToTime(CSec)=( a=(CSec), c=a%%100, a/=100, s=a%%60, a/=60, m=a%%60, h=a/60, h*1000000+m*10000+s*100+c )"
:: Define YYYYMMDD date to Julian Day Number conversion function and viceversa
set "DateToJDN(YMD)=( a=(YMD), y=a/10000, a%%=10000, m=a/100, d=a%%100, a=(m-14)/12, (1461*(y+4800+a))/4+(367*(m-2-12*a))/12-(3*((y+4900+a)/100))/4+d-32075 )"
set "JDNtoDate(JDN)=( a=(JDN), l=a+68569,n=(4*l)/146097,l=l-(146097*n+3)/4,i=(4000*(l+1))/1461001,l=l-(1461*i)/4+31,j=(80*l)/2447,d=l-(2447*j)/80,l=j/11,m=j+2-(12*l),y=100*(n-49)+i+l,y*10000+m*100+d )"
echo/
echo %time% & for /F "tokens=1-4 delims=:." %%a in ("%time%") do set "startTime=%%a%%b%%c%%d"
set /P "birthDate=Enter your birthdate in YYYY/MM/DD format: "
echo %time% & for /F "tokens=1-4 delims=:." %%a in ("%time%") do set "endTime=%%a%%b%%c%%d"
set /A "elapsed=%TimeToCSec(HMSC):HMSC=endTime% - %TimeToCSec(HMSC):HMSC=startTime%"
echo/
echo You took %elapsed:~0,-2%.%elapsed:~-2% seconds to enter previous line
REM As usual, you must adjust the next line accordingly to your locale date format
for /F "tokens=1-3 delims=/" %%a in ("%date%") do set "today=%%c%%a%%b"
set /A "total=%DateToJDN(YMD):YMD=today% - %DateToJDN(YMD):YMD=!birthDate:/=!%, a=total*100, years=a/36525, a%%=36525, months=a/3060, days=(a%%3060)/100"
echo/
echo You are %total% days old (%years% years, %months% months and %days% days approx.)
```

Antonio