Definition and use of arithmetic "functions" in Batch files
Moderator: DosItHelp
Re: Definition and use of arithmetic "functions" in Batch fi
No, the batch operator is defined on variable content and substitute strings with (other) strings.
The [] operator is defined on common terms to substitutes a term for a variable within another term, and therefore doesn't substitute functions or operators (or...) even if their labels share the same string:
- "%str:x=y%" equals "(y(y) y y(y))" (set "str=(x(x) x x(x))")
- "(x(x) x x(x))[x=y]" equals "(x(y) x x(y))"
But if names are unique and not contained in each other, then the batch operator could be used to simulate the [] operator (if you meant that).
penpen
The [] operator is defined on common terms to substitutes a term for a variable within another term, and therefore doesn't substitute functions or operators (or...) even if their labels share the same string:
- "%str:x=y%" equals "(y(y) y y(y))" (set "str=(x(x) x x(x))")
- "(x(x) x x(x))[x=y]" equals "(x(y) x x(y))"
But if names are unique and not contained in each other, then the batch operator could be used to simulate the [] operator (if you meant that).
penpen
Re: Definition and use of arithmetic "functions" in Batch fi
Code: Select all
@echo off
setlocal EnableDelayedExpansion
set "str=(x(x) x x(x))"
echo First: "%str:x=y%"
echo Second: "%str:(x)=(y)%"
set "[x=(x)"
set "y]=(y)"
echo Third: "!str:%[x%=%y]%!"
Although this "substitution operator" is interesting indeed, it bears no relation to the standard way that most programming languages use to define and invoke arithmetic functions!
penpen wrote:I must admit i never heard of a programming language that "naturally" supports this operator.
Then, why you introduced it in a thread whose purpose is to write something in the way most other programming languages does?
Antonio
Re: Definition and use of arithmetic "functions" in Batch fi
Aacini wrote:Then, why you introduced it in a thread whose purpose is to write something in the way most other programming languages does?
In the opening post you used the words:
Aacini wrote: a method that allows to use arithmetic expressions in Batch files in a way rather similar to arithmetic functions of other programming languages
I posted my suggestion before you have written:
Aacini wrote:the ability to take parameters in a way equivalent to real functions in other programming languages
So i couldn't take the last two points into account.Aacini wrote:The purpose is to write and execute arithmetic "functions" in a more standard way that may be comprehended by a larger group of people.
I think my suggestion is similar enough; our ways to assign variables don't differ that much, so i posted it, in detail:
Code: Select all
::define: additional "[],"
set "f(x)=(x+2)"
set "g(x)=([], x+3)"
:: invoke: additional "[]="
%f(x):x=1%
%g(x):[]=x=1%
Both versions are invoked in the same way: Replace a string with another (~ variable assignment).
In case of "%f(x):x=1%" the string to be replaced is mentioned within the variable name; but he has to know how to set the variable (and not doing "%f(x=1)%" or "%f(1)%").
In case of %g(x):[]=x=1% he has to know to replace "[]". If that is done for all functions it would be something that is easy to see (similar to setting x in f).
Similar for setting up a function: The user simply must know that he has to use parentheses around the formula (see: "set /A n=2 * %f(x):x=1% * 4"; result 10 versus 24), so the additional "[]," is just another fact to know
(and i initially i had my "consumer view", so i didn't made many thoughts about writing/defining the function, which was an error).
penpen
-
- Posts: 66
- Joined: 13 Jan 2015 06:55
Re: Definition and use of arithmetic "functions" in Batch fi
penpen wrote:Aacini wrote:Then, why you introduced it in a thread whose purpose is to write something in the way most other programming languages does?
In the opening post you used the words:Aacini wrote: a method that allows to use arithmetic expressions in Batch files in a way rather similar to arithmetic functions of other programming languages
I posted my suggestion before you have written:Aacini wrote:the ability to take parameters in a way equivalent to real functions in other programming languagesSo i couldn't take the last two points into account.Aacini wrote:The purpose is to write and execute arithmetic "functions" in a more standard way that may be comprehended by a larger group of people.
I think my suggestion is similar enough; our ways to assign variables don't differ that much, so i posted it, in detail:The user doesn't need to know, why "[]" is choosen (special operator) to be replaced (or he could use any other unique string to be replaced); for example he also doesn't know why in most programming languages the parameterlist is at the end of the function header: So this seemed to me less important.Code: Select all
::define: additional "[],"
set "f(x)=(x+2)"
set "g(x)=([], x+3)"
:: invoke: additional "[]="
%f(x):x=1%
%g(x):[]=x=1%
Both versions are invoked in the same way: Replace a string with another (~ variable assignment).
In case of "%f(x):x=1%" the string to be replaced is mentioned within the variable name; but he has to know how to set the variable (and not doing "%f(x=1)%" or "%f(1)%").
In case of %g(x):[]=x=1% he has to know to replace "[]". If that is done for all functions it would be something that is easy to see (similar to setting x in f).
Similar for setting up a function: The user simply must know that he has to use parentheses around the formula (see: "set /A n=2 * %f(x):x=1% * 4"; result 10 versus 24), so the additional "[]," is just another fact to know
(and i initially i had my "consumer view", so i didn't made many thoughts about writing/defining the function, which was an error).
penpen
Also with your method we can use multiple arguments:
Code: Select all
@echo off
set "f(x,y)=([],x+y)"
set /a result=%f(x,y):[]="x=3,y=5"%
echo %result%
EDIT: There is also caveat in this method: %x% is set to 3 and %y% is set 5 after executing.
Re: Definition and use of arithmetic "functions" in Batch fi
Well, as we can see, several different forms of using this technique are possible. For example, "args" name could be used instead of "[]" part this way:
... but this is not really necessary, because the "[]" part may be completelly omitted and the value of the variables (they are not "parameters"!) may be assigned before the invocation of the "function", as you shown before:
I am pretty sure that we could develop more different ways to use this technique, and this would be very good if the purpose of this thread would be "different ways to use this method". Unfortunately, the purpose of this thread is to use this method "in a way rather similar to arithmetic functions of other programming languages", as the first line of this thread indicate. Perhaps would be a good idea to open a new thread with the other goal and move to it the posts that does not belong to this one!
Code: Select all
set "sum(x,y,z)=(args, x+y+z)"
set /A "sum=%sum(x,y,z):args= x=1, y=2, z=3%"
... but this is not really necessary, because the "[]" part may be completelly omitted and the value of the variables (they are not "parameters"!) may be assigned before the invocation of the "function", as you shown before:
Code: Select all
set "sum(x,y,z)=(x+y+z)"
set /A "x=2, y=3, z=4, sum=%sum(x,y,z)%"
I am pretty sure that we could develop more different ways to use this technique, and this would be very good if the purpose of this thread would be "different ways to use this method". Unfortunately, the purpose of this thread is to use this method "in a way rather similar to arithmetic functions of other programming languages", as the first line of this thread indicate. Perhaps would be a good idea to open a new thread with the other goal and move to it the posts that does not belong to this one!
Re: Definition and use of arithmetic "functions" in Batch fi
There are news on this topic!
Below there is a new example that show how easy is to perform certain complex calculations when the "function" technique is combined with this expansion method to create an advanced arithmetic expression in a very simple way. I like this example!
I devised a way to include two parameters in the function definition and correctly manage they in the expression as separate entities. After developed it, the method seems obvious: if one %expansion% was needed in order to expand the first parameter, then a %second% !expansion! is needed to expand the second one. However, the way to implement this management use an interesting trick that could be useful in other scenarios; keep the eyes wide open in order to discover it!
The CALL and double percents trick may also be used to define two or more parameters. For example:
This is a complete "two parameters" example program:
Some of the most useful functions with two parameters are the boolean operators:
As said before, the CALL/double-percent trick may be used to define more than two parameters, but we can preserve the delayed expansion in the second parameter in order to avoid excessive CALL/percents. A very good example of a function with three parameters is the if-then-else (conditional operator) one.
In this function you may see the reason because I called this method "chained expansions"; you may appreciate this behavior in a clearer way if you activate the two ECHO commands.
You may use the boolean operator functions nested in the IF function, just pay attention to the order at which the "chained expansions" occur in both functions and make adjustments if neccessary. For example:
In this line the %first% and !delayed! expansions are used for the nested GTR(x,y) function, and the rest of %expansions% (second to fourth) for the IF function; be aware that two delayed expansions can not be nested (to look at the "chained expansions", ECHO this line with no, one, two and three CALL's!)
This line is a good example of the next point: the use of IF function combined with boolean operator functions may be less efficient than the direct writting of the equivalent expression or the use of another simpler function, like Max(x,y). However, if you need to write a long and complex if-then-else expression, the use of IF function may be simpler than trying to write the equivalent expression from scratch. You may also use the IF function as starting base until the code works properly and then get the equivalent direct expression from an ECHO command inserted before the SET, although the difference in efficiency between both forms would be minimal.
Antonio
Below there is a new example that show how easy is to perform certain complex calculations when the "function" technique is combined with this expansion method to create an advanced arithmetic expression in a very simple way. I like this example!
Code: Select all
@echo off
setlocal EnableDelayedExpansion
cls
echo Polynomial evaluation
echo/
echo Enter the polynomial coefficients separated by commas.
set /P "coeffs=For example, for y=x^2-4x-7 enter 1,-4,-7: "
echo/
set /P "range=Enter the initial,step,final values for x (i.e. -9,1,9): "
rem Define the function. See: http://www.dostips.com/forum/viewtopic.php?f=3&t=6429
set "f(x)=%coeffs:,=,y=y*x+%"
echo/
echo x y=%f(x)%
echo --- ------------
for /L %%x in (%range%) do (
set /A "y=!f(x):x=%%x!"
echo %%x !y!
)
I devised a way to include two parameters in the function definition and correctly manage they in the expression as separate entities. After developed it, the method seems obvious: if one %expansion% was needed in order to expand the first parameter, then a %second% !expansion! is needed to expand the second one. However, the way to implement this management use an interesting trick that could be useful in other scenarios; keep the eyes wide open in order to discover it!
Code: Select all
setlocal EnableDelayedExpansion
set "Max(x,y)=( z=(x),^!Ma1(y)"
set "Ma1(y)=?=((z-(y))>>31)+1, ?*z + ^!?*(y) )"
set /A "max=%Max(x,y):x=10%:y=20!"
The CALL and double percents trick may also be used to define two or more parameters. For example:
Code: Select all
set "RandomRange(x,y)=( z=(x),rnd=^!random^!,%%Random1(y)"
set "Random1(y)=((y)-z+1)*rnd/32768+z )"
call set /A "rnd=%RandomRange(x,y):x=10%:y=20%%"
This is a complete "two parameters" example program:
Code: Select all
@echo off
:: Define Max(x,y) function with two *real* parameters
setlocal EnableDelayedExpansion
set "Max(x,y)=( z=(x),^!Ma1(y)"
set "Ma1(y)=?=((z-(y))>>31)+1, ?*z + ^!?*(y) )"
set /P "numbers=Enter two numbers separated by space: "
for /F "tokens=1,2" %%a in ("%numbers%") do set /A one=%%a, two=%%b
set /A "max=%Max(x,y):x=one%:y=two!"
echo The max is %max%
:: Define Max(x,y) function with two parameters via CALL/double-percents instead Delayed Expansion
set "Max(x,y)=( z=(x),%%Ma1(y)"
set "Ma1(y)=?=((z-(y))>>31)+1, ?*z + ^!?*(y) )"
call set /A "max=%Max(x,y):x=one%:y=two%%"
echo The max is %max% (CALL method)
:: Define RandomRange(x,y) function with two parameters via DelayedExpansion
set "RandomRange(x,y)=( z=(x),rnd=^!random^!,^!Random1(y)"
set "Random1(y)=((y)-z+1)*rnd/32768+z )"
set /A "rnd=%RandomRange(x,y):x=one%:y=two!"
echo Random number in this range: %rnd%
:: Define RandomRange(x,y) function with two parameters via CALL/double-percents
set "RandomRange(x,y)=( z=(x),rnd=^!random^!,%%Random1(y)"
set "Random1(y)=((y)-z+1)*rnd/32768+z )"
call set /A "rnd=%RandomRange(x,y):x=one%:y=two%%"
echo Random number in this range: %rnd% (CALL method)
Some of the most useful functions with two parameters are the boolean operators:
Code: Select all
@echo off
setlocal EnableDelayedExpansion
:: Define functions for boolean operations
set "GTR(x,y)=(z=(x)-1,^!gte(y)"
set "GEQ(x,y)=(z=(x),^!gte(y)"
set "gte(y)=((z-(y))>>31)+1 )"
set "LSS(x,y)=(z=(x)+1,^!lse(y)"
set "LEQ(x,y)=(z=(x),^!lse(y)"
set "lse(y)=(((y)-z)>>31)+1 )"
set "EQU(x,y)=(z=(x),^!eq1(y)"
set "eq1(y)=^!(z-(y)) )"
set "NEQ(x,y)=(z=(x),^!ne1(y)"
set "ne1(y)=^!^!(z-(y)) )"
set /P "numbers=Enter two numbers separated by space: "
for /F "tokens=1,2" %%a in ("%numbers%") do set /A one=%%a, two=%%b
set /A "gtr=%GTR(x,y):x=one%:y=two!"
set /A "geq=%GEQ(x,y):x=one%:y=two!"
set /A "lss=%LSS(x,y):x=one%:y=two!"
set /A "leq=%LEQ(x,y):x=one%:y=two!"
set /A "equ=%EQU(x,y):x=one%:y=two!"
set /A "neq=%NEQ(x,y):x=one%:y=two!"
set "ans[0]=NOT "
echo/
echo %one% is !ans[%gtr%]!GTR than %two%
echo %one% is !ans[%geq%]!GEQ than %two%
echo %one% is !ans[%lss%]!LSS than %two%
echo %one% is !ans[%leq%]!LEQ than %two%
echo %one% is !ans[%equ%]!EQU than %two%
echo %one% is !ans[%neq%]!NEQ than %two%
As said before, the CALL/double-percent trick may be used to define more than two parameters, but we can preserve the delayed expansion in the second parameter in order to avoid excessive CALL/percents. A very good example of a function with three parameters is the if-then-else (conditional operator) one.
Code: Select all
@echo off
setlocal EnableDelayedExpansion
set "IF(test,then,else)=( ?=(test),^!IFT(then,else)"
set "IFT(then,else)=t=(then),%%IFTE(else)"
set "IFTE(else)=^!^!?*t + ^!?*(else) )"
set /P "value=Enter a value different than 0 for 123, or 0 for 456: "
REM ECHO set /A "result=%IF(test,then,else):test=value%:then=123!:else=456%%"
REM CALL ECHO set /A "result=%IF(test,then,else):test=value%:then=123!:else=456%%"
call set /A "result=%IF(test,then,else):test=value%:then=123!:else=456%%"
echo Result: %result%
In this function you may see the reason because I called this method "chained expansions"; you may appreciate this behavior in a clearer way if you activate the two ECHO commands.
You may use the boolean operator functions nested in the IF function, just pay attention to the order at which the "chained expansions" occur in both functions and make adjustments if neccessary. For example:
Code: Select all
set "IF(test,then,else)=( ?=(test),%%IFT(then,else)"
set "IFT(then,else)=t=(then),%%IFTE(else)"
set "IFTE(else)=^!^!?*t + ^!?*(else) )"
call call call set /A "max=%%IF(test,then,else):test=%GTR(x,y):x=one%:y=two!%%:then=one%%%%:else=two%%%%%%%%"
In this line the %first% and !delayed! expansions are used for the nested GTR(x,y) function, and the rest of %expansions% (second to fourth) for the IF function; be aware that two delayed expansions can not be nested (to look at the "chained expansions", ECHO this line with no, one, two and three CALL's!)
This line is a good example of the next point: the use of IF function combined with boolean operator functions may be less efficient than the direct writting of the equivalent expression or the use of another simpler function, like Max(x,y). However, if you need to write a long and complex if-then-else expression, the use of IF function may be simpler than trying to write the equivalent expression from scratch. You may also use the IF function as starting base until the code works properly and then get the equivalent direct expression from an ECHO command inserted before the SET, although the difference in efficiency between both forms would be minimal.
Antonio
Re: Definition and use of arithmetic "functions" in Batch fi
OperatorGK's last edit let me notice that it might not be a good idea to change variables without limitations within a formula; examples:
- a in Abs(x)
- z in Max(x,y)
- t in IF(test,then,else)
If someone writes a library with such functions, then another user connot be sure that his variables won't change.
She/he also cannot restore these variables in the standard way (by appending ", x=%x%", or similar), because its names are unpredictable (as long as this user doesn't lookup every function).
So it might be better to use variable names of a specific format, for example variables "_1, _2, _3, ..." so the user could easily avoid using these variables.
penpen
- a in Abs(x)
- z in Max(x,y)
- t in IF(test,then,else)
If someone writes a library with such functions, then another user connot be sure that his variables won't change.
She/he also cannot restore these variables in the standard way (by appending ", x=%x%", or similar), because its names are unpredictable (as long as this user doesn't lookup every function).
So it might be better to use variable names of a specific format, for example variables "_1, _2, _3, ..." so the user could easily avoid using these variables.
penpen
Re: Definition and use of arithmetic "functions" in Batch fi
There are very interesting news on this topic!
After defining the "function" technique I wanted to use the same method to process characters, so certain frequent manipulations (like StrLen function) could be performed in the same way. However, an arithmetic expression is performed in the same command that assign its value to a variable, but there is no such equivalent for character data. In this case the data is generated by any command and is taken and assigned to a variable via a separate FOR /F command. This way, in order to simulate the "function" method for character data we must start defining a "function" or "macro" comprised of the FOR /F required to execute a command and assign its output to a variable, like this one:
... that may be used via the same format of the "functions", that is:
We may make good use of the FOR /F command and also get several lines displayed by the command and assign all of them into a long string, and enclose each line by an optional delimiter (like quotes), and even assign each line to a separate element of an array.
These SET macros may be used in combination with any command, but we may also define a "function" that perform a certain manipulation (like StrLen) specifically designed to be used inside SET macro. Below there are the definition of the two forms of SET macro (output to a single line or to an array) and a couple examples of "functions" designed for them. The main problems when writing these functions are the nesting of commands and the fact that commands placed into a nested FOR are executed in the command-line context.
These SET macro/function combinations have the same advantages of the previous "functions": they execute faster than the original multi-line versions of the same code.
Antonio
After defining the "function" technique I wanted to use the same method to process characters, so certain frequent manipulations (like StrLen function) could be performed in the same way. However, an arithmetic expression is performed in the same command that assign its value to a variable, but there is no such equivalent for character data. In this case the data is generated by any command and is taken and assigned to a variable via a separate FOR /F command. This way, in order to simulate the "function" method for character data we must start defining a "function" or "macro" comprised of the FOR /F required to execute a command and assign its output to a variable, like this one:
Code: Select all
set "SET(output,command)=for /F "delims=" %%a in ('command') do set "output=%%~a""
... that may be used via the same format of the "functions", that is:
Code: Select all
%SET(output,command):command=echo Hello World%
echo %output%
We may make good use of the FOR /F command and also get several lines displayed by the command and assign all of them into a long string, and enclose each line by an optional delimiter (like quotes), and even assign each line to a separate element of an array.
These SET macros may be used in combination with any command, but we may also define a "function" that perform a certain manipulation (like StrLen) specifically designed to be used inside SET macro. Below there are the definition of the two forms of SET macro (output to a single line or to an array) and a couple examples of "functions" designed for them. The main problems when writing these functions are the nesting of commands and the fact that commands placed into a nested FOR are executed in the command-line context.
Code: Select all
@echo off
setlocal EnableDelayedExpansion
rem Definition of the two basic forms of SET macro
set "_bound="
set "SET(output,command)=set "output="&(for /F "delims=" %%a in ('command') do set "output=^^^!output^^^! ^^^!_bound^^^!%%~a^^^!_bound^^^!")&set "output=^^^!output:~1^^^!""
set "SET(output[],command)=set _0=0&(for /F "delims=" %%a in ('command') do set /A _0+=1&set "output[^^^!_0^^^!]=%%~a")&set /A output.length=_0"
cls
echo Examples of use of SET macro
echo/
set "wildCard=*.*"
set /P "wildCard=Enter a wild card: "
echo/
echo List of files:
%SET(output,command):command=dir /B !wildCard!%
echo %output%
echo/
echo List of quoted files:
set _bound="
%SET(output,command):command=dir /B !wildCard!%
echo %output%
echo/
echo List of files in an array:
%SET(output[],command):command=dir /B !wildCard!%
for /L %%i in (1,1,%output.length%) do echo !output[%%i]!
echo/
echo/
echo Definition of ToUpper(str) function for SET macro
echo/
set ToUpper(str)=cmd /V:ON /C "set _0=^!str^!&(for %%a in (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) do @set "_0=^^^!_0:%%a=%%a^^^!")&echo "^^^!_0^^^!""
set /P "string=Enter a string: "
set "_bound="
%SET(output,command):command="!ToUpper(str):str=string!"%
echo ToUpper: %output%
echo/
echo/
echo Definition of StrLen(str) function for SET macro
echo/
set StrLen(str)=cmd /V:ON /C "set _0=0^!str^!&>NUL set /A _1=0,_2=4096&(for /L %%i in (12,-1,0) do @>NUL set /A _3=_1+_2,_2/=2&(for /F %%n in ("^^^!_3^^^!") do @if "^^^!_0:~%%n,1^^^!" neq "" set _1=^^^!_3^^^!))&echo ^!_1^!"
set /P "string=Enter a string: "
%SET(output,command):command="!StrLen(str):str=string!"%
set "length=%output% "
set /A tens=output/10, units=output%%10
set "ten=123456789 "
set /P "=Length: %length:~0,4%-> " < NUL
for /L %%i in (1,1,%tens%) do set /P "=%ten%" < NUL
echo(!ten:~0,%units%!
These SET macro/function combinations have the same advantages of the previous "functions": they execute faster than the original multi-line versions of the same code.
Antonio
-
- Expert
- Posts: 960
- Joined: 15 Jun 2012 13:16
- Location: Italy, Rome
Re: Definition and use of arithmetic "functions" in Batch fi
Hi,
I need some assistence for a new fuction that used a previous one.
This is the my attempt to define Integer LN (Natural Logaritm) using Borchardt's algorithm :
There are some bugs that I will fix later...
It is possible to get a Function inside another or need more steps?
It is possible merge more steps in a single line?
Einstein1969
I need some assistence for a new fuction that used a previous one.
This is the my attempt to define Integer LN (Natural Logaritm) using Borchardt's algorithm :
Code: Select all
@echo off
setlocal EnableDelayedExpansion
set "Sqrt(N)=( M=(N),x=M/(11*1024)+40, x=(M/x+x)>>1, x=(M/x+x)>>1, x=(M/x+x)>>1, x=(M/x+x)>>1, x=(M/x+x)>>1, x+=(M-x*x)>>31 )"
rem http://math.stackexchange.com/questions/75074/an-alternative-way-to-calculate-logx
for %%z in (1, 2, 3, 4, 9, 10, 16, 25, 100, 511, 512, 1000, 10000,
65535, 65536, 100000, 131071, 131072, 262143, 262144, 393215, 393216, 800000
1000000, 2085999, 2086000, 5000000, 10000000, 100000000, 200000000, 1000000000, 2147395600, 2147483647) do (
set /A "last_sqrt=!Sqrt(N):N=%%z!"
set /A "N=%%z, a0=(1+N)/2, b0=last_sqrt, a1=(a0+b0)/2, sqr=a1*b0"
For %%s in (!sqr!) do set /A "last_sqrt=!Sqrt(N):N=%%s!"
set /A "b1=last_sqrt, a2=(a1+b1)/2, sqr=a2*b1"
For %%s in (!sqr!) do set /A "last_sqrt=!Sqrt(N):N=%%s!"
set /A "b2=last_sqrt, a3=(a2+b2)/2, sqr=a3*b2"
For %%s in (!sqr!) do set /A "last_sqrt=!Sqrt(N):N=%%s!"
set /A "b3=last_sqrt, a4=(a3+b3)/2, sqr=a4*b3"
For %%s in (!sqr!) do set /A "last_sqrt=!Sqrt(N):N=%%s!"
set /A "N=%%z, b4=last_sqrt, ln=2*(N-1)/(a4+b4), lnp=2*(N-1)/(a3+b3)"
echo %%z ln:!ln! lnp:!lnp!
rem echo a0:!a0! b0:!b0! a1:!a1! b1:!b1! a2:!a2! b2:!b2! a3:!a3! b3:!b3! a4:!a4! b4:!b4!
rem echo(
)
pause
exit/b
There are some bugs that I will fix later...
It is possible to get a Function inside another or need more steps?
It is possible merge more steps in a single line?
Einstein1969
-
- Expert
- Posts: 960
- Joined: 15 Jun 2012 13:16
- Location: Italy, Rome
Re: Definition and use of arithmetic "functions" in Batch fi
trebor68 wrote:The Sign fuction is defineted:
Value x < 0 is Sgn(x) = -1
Value x = 0 is Sgn(x) = 0
Value x > 0 is Sgn(x) = 1
See also: https://en.wikipedia.org/wiki/Sign_functionCode: Select all
D:\CMDVerz>set /a a=32,"(a>>31)+!(a>>31)*!!a"
1
D:\CMDVerz>set /a a=0,"(a>>31)+!(a>>31)*!!a"
0
D:\CMDVerz>set /a a=-32,"(a>>31)+!(a>>31)*!!a"
-1
D:\CMDVerz>
This is solution that not use the ! (for escape problem)
Code: Select all
C:\Users\ACER>set /A "n=32, s=(n>>31)|((-n>>31)&1)"
1
C:\Users\ACER>set /A "n=0, s=(n>>31)|((-n>>31)&1)"
0
C:\Users\ACER>set /A "n=-30, s=(n>>31)|((-n>>31)&1)"
-1
Einstein1969
Re: Definition and use of arithmetic "functions" in Batch files
There are new developments on this topic, this time related to the definition of functions with several parameters. I strongly suggest you to review the whole thread before review this reply, in order to remember the methods used here...
Lets start with the simplest case: a function with two parameters. If a list of several expressions separated by commas is assigned to a variable in a SET /A command, the variable gets the value of the first expression, but if the list is enclosed in parentheses, then the variable gets the value of the last expression. This behavior allows to define a function with two parameters and easily separate them by just enclosing the parameters pair between parentheses in order to get the second parameter:
Output:
A "SET /A" arithmetic expression don't provides a method to separate more than two parameters, so we need to use the standard "SET" tricks in order to do so. Although doing that will not return a result in the simple and direct way than the numeric "SET /A" does, this non-numeric "function" provides a method to encapsulate in a single line a series of managements that are used in a very simple way, that is the original purpose of this thread anyway. Besides, the use of standard SET command allows to manage non-numeric parameters.
The method used to separate an "a,b,c" parameter list in individual "a", "b", "c" elements is explained with detail at this post.
Output:
Note that the definition of SetVars "function" follows a well defined scheme. This point means that the creation of a function of this type with any number of parameters could be automatized via a subroutine:
Output:
Finally, lets review a different example: instead of define a function with several parameters, lets define a function with one parameter that is the name of a variable, and process it as a string in a very different way:
Output:
Antonio
Lets start with the simplest case: a function with two parameters. If a list of several expressions separated by commas is assigned to a variable in a SET /A command, the variable gets the value of the first expression, but if the list is enclosed in parentheses, then the variable gets the value of the last expression. This behavior allows to define a function with two parameters and easily separate them by just enclosing the parameters pair between parentheses in order to get the second parameter:
Code: Select all
@echo off
setlocal EnableDelayedExpansion
rem Definition of a function with two numeric parameters
set "TwoParams(x,y)= x=x,y , y=(x,y)"
rem Usage example
set /A "test=%TwoParams(x,y):x,y=123,456%"
echo x=%x%, y=%y%
rem Practical example: MAXimum and MINimum functions
set "Max(x,y)=( x=x,y, y=(x,y), c=(x-y>>31)+1, c*x+^^^!c*y )"
set "Min(x,y)=!Max(x,y):x-y=y-x!"
echo/
set /P "numbers=Enter two numbers separated by a space: "
set /A "n1=%numbers: =,n2=%, max=%Max(x,y):x,y=n1,n2%, min=%Min(x,y):x,y=n1,n2%"
echo Max = %max%, Min = %min%
rem Practical example: Add/Subtract two "1+six_digits" values representing times
rem Definition of the AddTimes function with two "1HHMMSS" parameters
set "AddTimes(t1,t2)=( t1=t1,t2,t2=(t1,t2), s1=t1%%100,t1/=100,s1+=t1%%100*60,t1/=100,s1+=t1%%100*60*60, s2=t2%%100,t2/=100,s2+=t2%%100*60,t2/=100,s2+=t2%%100*60*60, r=s1+s2, res=r%%60,r/=60,res+=r%%60*100,r/=60,res+(r+100)*10000 )"
rem Definition of the derived SubTimes function
set "SubTimes(t1,t2)=!AddTimes(t1,t2):s1+s2=s1-s2!"
echo/
set /P "time1=Enter base time in HH:MM:SS format: "
set /P "time2=Enter delta time, same format: "
set /A "add=!AddTimes(t1,t2):t1,t2=1%time1::=%,1%time2::=%!, sub=!SubTimes(t1,t2):t1,t2=1%time1::=%,1%time2::=%!"
echo ---------
echo The Add result is: %add:~-6,2%:%add:~-4,2%:%add:~-2%
echo ---------
echo The Sub result is: %sub:~-6,2%:%sub:~-4,2%:%sub:~-2%
Code: Select all
x=123, y=456
Enter two numbers separated by a space: 123 456
Max = 456, Min = 123
Enter base time in HH:MM:SS format: 10:45:15
Enter delta time, same format: 00:30:30
---------
The Add result is: 11:15:45
---------
The Sub result is: 10:14:45
The method used to separate an "a,b,c" parameter list in individual "a", "b", "c" elements is explained with detail at this post.
Code: Select all
@echo off
setlocal EnableDelayedExpansion
rem Definition of a non-numeric "function" with three parameters
set SetVars(a,b,c)=set "a=a,b,c" ^& set "b=^!a:*,=^!" ^& call set "a=%%a:,^!b^!=%%" ^& set "c=^!b:*,=^!" ^& call set "b=%%b:,^!c^!=%%"
rem Usage examples
%SetVars(a,b,c):a,b,c=10,20,30%
echo Three numeric values: a="%a%", b="%b%", c="%c%"
%SetVars(a,b,c):a,b,c=First value,This is the second value,And this is the last one%
echo Three string values: a="%a%", b="%b%", c="%c%"
Code: Select all
Three numeric values: a="10", b="20", c="30"
Three string values: a="First value", b="This is the second value", c="And this is the last one"
Code: Select all
@echo off
setlocal EnableDelayedExpansion
rem Example of automatized definition of a "function" with four parameters
call :DefineSetVars a b c d
echo Defined function:
echo SetVars(a,b,c,d)=!SetVars(a,b,c,d)!
rem Usage example
%SetVars(a,b,c,d):a,b,c,d=10,20,30,40%
echo Four numeric values: a="%a%", b="%b%", c="%c%", d="%d%"
goto :EOF
rem Subroutine to create a base "function" with several parameters
:DefineSetVars var1 var2 var3 ...
setlocal EnableDelayedExpansion
set "last="
for %%a in (%*) do (
if not defined last (
set "expr=%*"
set "expr=!expr: =,!"
set expr=SetVars(!expr!^)=set "%%a=!expr!"
) else (
set expr=!expr! ^& set "%%a=^^^!!last!:*,=^^^!" ^& call set "!last!=%%!last!:,^^^!%%a^^^!=%%"
)
set "last=%%a"
)
for /F "delims=" %%a in ("!expr!") do (
endlocal
set "%%a"
)
exit /B
Code: Select all
Defined function:
SetVars(a,b,c,d)=set "a=a,b,c,d" & set "b=!a:*,=!" & call set "a=%a:,!b!=%" & set "c=!b:*,=!" & call set "b=%b:,!c!=%" & set "d=!c:*,=!" & call set "c=%c:,!d!=%"
Four numeric values: a="10", b="20", c="30", d="40"
Code: Select all
@echo off
setlocal EnableDelayedExpansion
rem Define the StrLen(var) "function" with one string *variable* as parameter
set StrLen(var)=set "str=0^!var^!" ^& set /A "l=0,n=b=1<<12"
for /L %%i in (1,1,13) do set StrLen(var)=!StrLen(var)! ^& call set "c=%%str:~^!n^!,1%%" ^& (if "^!c^!" neq "" set /A l=n) ^& set /A "n=l+(b>>=1)"
set StrLen(var)=!StrLen(var)! ^& set /A "StrLen=l"
rem Example of use of StrLen(var) function
:loop
set "str="
set /P "str=Enter a string: "
if not defined str goto :EOF
%StrLen(var):var=str%
echo The length is: %StrLen%
echo/
goto loop
Code: Select all
Enter a string: Nineteen characters
The length is: 19
Enter a string: TenLetters
The length is: 10
Enter a string:
Re: Definition and use of arithmetic "functions" in Batch files
This is syntactic sugar Thanks for sharing.
Steffen
Steffen
-
- Expert
- Posts: 960
- Joined: 15 Jun 2012 13:16
- Location: Italy, Rome
Re: Definition and use of arithmetic "functions" in Batch files
Hi,
there is an error on function:
it should be
can someone confirm?
there is an error on function:
Code: Select all
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 )"
Code: Select all
set "CSecToHMSC(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 )"