Algorithmic conditions, and returns????

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Message
Author
IcarusLives
Posts: 175
Joined: 17 Jan 2016 23:55

Algorithmic conditions, and returns????

#1 Post by IcarusLives » 29 Mar 2018 15:44

I have a rather strange request, but I'm sure that if anyone can conjure this up, and then explain it to me, it would definitely be this place.

I am looking for something really simple.. Typically we have this:

Code: Select all

if CONDITION ( do this ) else ( do this )
I'm looking for a way to make this comparison with pure maths?

Also, if it's possible to utilize the way the math can compare two numbers, or compare another set? Perhaps this code will explain better?

Code: Select all

if (pos.x > width || pos.x < 0) {
      vel.x *= -1;
}
This is some java code from a project I did, and as you can see, java allows you to say.. "If X is gtr width OR if X is lss 0 then set the velocity*=-1"

So essentially, my question is how could I do such a comparison in batch with pure math? NOT using an IF statement.

Also, if it can be done, PLEASE can you explain it to me? Thank you!

aGerman
Expert
Posts: 4678
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Algorithmic conditions, and returns????

#2 Post by aGerman » 29 Mar 2018 16:32

You're looking for logical operators.
That topic provides a workaround:
viewtopic.php?f=3&t=4308

Steffen

IcarusLives
Posts: 175
Joined: 17 Jan 2016 23:55

Re: Algorithmic conditions, and returns????

#3 Post by IcarusLives » 29 Mar 2018 16:57

This isn't quite what I'm looking for.

Really, I would like to ONLY use set /a for this if at all possible. I do NOT want to use the actual IF statement.

Below is the %getDistance% macro algorithm. Aacini had made this for me a while back upon request and it's been EXTREMELY useful ever sense.

Code: Select all

set getDistance=for %%# in (1 2) do if %%#==2 ( for /f "tokens=1-5" %%1 in ("^!args^!") do (%\n%
    set /a "%%5=( ?=((((((%%1 - %%2))>>31|1)*((%%1 - %%2)))-((((%%3 - %%4))>>31|1)*((%%3 - %%4))))>>31)+1, ?*(2*((((%%1 - %%2))>>31|1)*((%%1 - %%2)))-((((%%3 - %%4))>>31|1)*((%%3 - %%4)))-(((((%%1 - %%2))>>31|1)*((%%1 - %%2)))-((((%%3 - %%4))>>31|1)*((%%3 - %%4))))) + ^^^!?*(((((%%1 - %%2))>>31|1)*((%%1 - %%2)))-((((%%3 - %%4))>>31|1)*((%%3 - %%4)))-(((((%%1 - %%2))>>31|1)*((%%1 - %%2)))-((((%%3 - %%4))>>31|1)*((%%3 - %%4)))*2)) )"%\n%
)) else set args=
I would really like to simulate an IF condition the same way.

aGerman
Expert
Posts: 4678
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Algorithmic conditions, and returns????

#4 Post by aGerman » 29 Mar 2018 17:28

The logical operators && and || exist in Batch, but only for the errorlevel. You can try to provoke a SET /A error. E.g. division by zero.

Code: Select all

@echo off &setlocal
set /a "x=3, y=2"

if %x% lss %y% (echo less than) else echo greater than or equal
2>nul set /a "1/((x-y)>>31)" && (echo less than) || echo greater than or equal
pause
The Most Significant Bit of a negative number is 1 and for a positive number is zero. The Shift Right operator shifts always the MSB in. Thus, >>31 results in -1 (all bits set to 1) if the result of x-y was negative. Otherwise it's 0 (all bits set to 0) if the result of x-y was zero or positive.

Steffen

penpen
Expert
Posts: 2009
Joined: 23 Jun 2013 06:15
Location: Germany

Re: Algorithmic conditions, and returns????

#5 Post by penpen » 29 Mar 2018 19:03

You could implement a mathematical function as proposed by Aacini:
viewtopic.php?f=3&t=6744.

A little math library is created by einstein1969:
viewtopic.php?f=3&t=5819.

Then you should simplify your task (reduce the needed helper functions; compute a value in all if-cases) and then create a formula that computes what you need; a possibility:

Code: Select all

@echo off
setlocal enableExtensions enableDelayedExpansion
set /a "pos.x=10, width=5, vel.x=-12"

set "LssZero(x)=(-((x)>>31))"

:: short explaination
:: 1. "pos.x > width" == "0 > (width-pos.x)" == "(width-pos.x)<0"
:: 2. "if (pos.x > width || pos.x < 0) { vel.x *= -1; }"
:: == "if (pos.x > width || pos.x < 0) { vel.x *= -1; } else { vel.x *= 1; }"
:: == "vel.x *= (pos.x > width || pos.x < 0) ? -1 : 1;"
:: == "vel.x *= ( (pos.x > width || pos.x < 0) ? -2 : 0 )+1;"
:: == "vel.x *= ( (pos.x > width || pos.x < 0) ? -1 : 0 )*2+1;"
:: == "vel.x *= -( (pos.x > width || pos.x < 0) ? 1 : 0 )*2+1;"
:: == "vel.x *= (-( (pos.x > width || pos.x < 0) ? 1 : 0 )<<1)+1;"
:: == "vel.x *= (-(((pos.x > width) ? 1 : 0)|((pos.x < 0) ? 1 : 0))<<1)+1;"
:: == " vel.x *= (-((((width-pos.x)<0) ? 1: 0)|((pos.x < 0) ? 1: 0))<<1)+1;"
set /a "vel.x *= (-(%LssZero(x):x=width-pos.x%|%LssZero(x):x=pos.x%)<<1)+1"

set "vel.x"
goto :eof
penpen

IcarusLives
Posts: 175
Joined: 17 Jan 2016 23:55

Re: Algorithmic conditions, and returns????

#6 Post by IcarusLives » 29 Mar 2018 19:32

penpen wrote:
29 Mar 2018 19:03
You could implement a mathematical function as proposed by Aacini:
viewtopic.php?f=3&t=6744.

A little math library is created by einstein1969:
viewtopic.php?f=3&t=5819.

Then you should simplify your task (reduce the needed helper functions; compute a value in all if-cases) and then create a formula that computes what you need; a possibility:

Code: Select all

@echo off
setlocal enableExtensions enableDelayedExpansion
set /a "pos.x=10, width=5, vel.x=-12"

set "LssZero(x)=(-((x)>>31))"

:: short explaination
:: 1. "pos.x > width" == "0 > (width-pos.x)" == "(width-pos.x)<0"
:: 2. "if (pos.x > width || pos.x < 0) { vel.x *= -1; }"
:: == "if (pos.x > width || pos.x < 0) { vel.x *= -1; } else { vel.x *= 1; }"
:: == "vel.x *= (pos.x > width || pos.x < 0) ? -1 : 1;"
:: == "vel.x *= ( (pos.x > width || pos.x < 0) ? -2 : 0 )+1;"
:: == "vel.x *= ( (pos.x > width || pos.x < 0) ? -1 : 0 )*2+1;"
:: == "vel.x *= -( (pos.x > width || pos.x < 0) ? 1 : 0 )*2+1;"
:: == "vel.x *= (-( (pos.x > width || pos.x < 0) ? 1 : 0 )<<1)+1;"
:: == "vel.x *= (-(((pos.x > width) ? 1 : 0)|((pos.x < 0) ? 1 : 0))<<1)+1;"
:: == " vel.x *= (-((((width-pos.x)<0) ? 1: 0)|((pos.x < 0) ? 1: 0))<<1)+1;"
set /a "vel.x *= (-(%LssZero(x):x=width-pos.x%|%LssZero(x):x=pos.x%)<<1)+1"

set "vel.x"
goto :eof
penpen
This is basically EXACTLY what I'm looking for. My problem now lies with HOW do I write such a function? (The actual maths)? In the %getDistance% macro I posted above, it does contain somewhat of an "if" because it checks for the larger integer, but I don't know how it does that..

Aacini
Expert
Posts: 1914
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Algorithmic conditions, and returns????

#7 Post by Aacini » 29 Mar 2018 19:33

Perhaps this thread may help you.

Although not directly related to your request, I invite you to review this topic... 8)

Antonio

IcarusLives
Posts: 175
Joined: 17 Jan 2016 23:55

Re: Algorithmic conditions, and returns????

#8 Post by IcarusLives » 29 Mar 2018 19:51

Aacini, this is brilliant! Thank you for sharing!!!

aGerman
Expert
Posts: 4678
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Algorithmic conditions, and returns????

#9 Post by aGerman » 30 Mar 2018 08:32

Code: Select all

@echo off &setlocal

REM ----- return 0 if false or 1 if true -----
set "LSS(x,y)=(((x-y)>>31)&1)"                     &REM <
set "LEQ(x,y)=((~(y-x)>>31)&1)"                    &REM <=
set "GTR(x,y)=(((y-x)>>31)&1)"                     &REM >
set "GEQ(x,y)=((~(x-y)>>31)&1)"                    &REM >=
set "EQU(x,y)=(((~(y-x)>>31)&1)&((~(x-y)>>31)&1))" &REM ==
set "NEQ(x,y)=((((x-y)>>31)&1)|(((y-x)>>31)&1))"   &REM !=

REM ----- values of b1 and b2 have to be either 0 or 1 -----
REM ----- return 0 if false or 1 if true -----
set "AND(b1,b2)=(b1&b2)"                           &REM &&
set "OR(b1,b2)=(b1|b2)"                            &REM ||

REM ----- ternary operation: return_value = (bool) ? value1_if_true : value2_if_false -----
REM ----- value of bool has to be either 0 or 1 -----
REM ----- returns v1 if bool=1 or v2 if bool=0 -----
set "TERN(bool,v1,v2)=((bool*v1)|((~bool&1)*v2))"  &REM ?:


REM Examples for calculations of (a > b || a < 0) ? c * -1 : c
set /a "a=-1, b=-3, c=-5"
call :calc

set /a "a=-1, b=3, c=-5"
call :calc

set /a "a=1, b=-3, c=-5"
call :calc

set /a "a=1, b=3, c=-5"
call :calc

pause
exit /b


:calc
setlocal
<nul set /p "=c = (%a% > %b% || %a% < 0) ? %c% * -1 : %c%" &echo(
set /a "x=a, y=b, b1=%GTR(x,y)%,   y=0, b2=%LSS(x,y)%,   bool=%OR(b1,b2)%,   v1=c*-1, v2=c, c=%TERN(bool,v1,v2)%"
echo c = %c%
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
endlocal &exit /b
I refrained from using logical NOT (!) in case delayed expansion matters.

Steffen
Last edited by aGerman on 31 Mar 2018 04:32, edited 1 time in total.
Reason: comments and examples updated

IcarusLives
Posts: 175
Joined: 17 Jan 2016 23:55

Re: Algorithmic conditions, and returns????

#10 Post by IcarusLives » 30 Mar 2018 09:50

aGerman wrote:
30 Mar 2018 08:32

Code: Select all

@echo off &setlocal EnableDelayedExpansion

REM ----- return false=0 or true=1 -----
set "LSS(x,y)=(((x-y)>>31)&1)"
set "LEQ(x,y)=((~(y-x)>>31)&1)"
set "GTR(x,y)=(((y-x)>>31)&1)"
set "GEQ(x,y)=((~(x-y)>>31)&1)"
set "EQU(x,y)=(((~(y-x)>>31)&1)&((~(x-y)>>31)&1))"
set "NEQ(x,y)=((((x-y)>>31)&1)|(((y-x)>>31)&1))"
set "AND(b1,b2)=(b1&b2)"
set "OR(b1,b2)=(b1|b2)"

REM -----(true) ? value1 : value2
set "TERN(bool,v1,v2)=((bool*v1)|((~bool&1)*v2))"


REM Example
set /a "a=-1, b=4, c=-12"

REM (a > b || a < 0) ? c *= -1 : c
set /a "x=a, y=b, b1=%GTR(x,y)%,   y=0, b2=%LSS(x,y)%,   bool=%OR(b1,b2)%,   v1=c*-1, v2=c, c=%TERN(bool,v1,v2)%"
echo %c%

pause
I refrained from using logical NOT (!) in case delayed expansion matters.

Steffen
*drool* Oh.. Sweet Jesus, I knew I loved this site.

Thank you all for your sharing and contribution! This is all exactly what I was looking for, and my problem is now solved!!

THANK YOU SO MUCH!

penpen
Expert
Posts: 2009
Joined: 23 Jun 2013 06:15
Location: Germany

Re: Algorithmic conditions, and returns????

#11 Post by penpen » 30 Mar 2018 10:46

IcarusLives wrote:
29 Mar 2018 19:32
My problem now lies with HOW do I write such a function? (The actual maths)? In the %getDistance% macro I posted above, it does contain somewhat of an "if" because it checks for the larger integer, but I don't know how it does that..
IcarusLives wrote:
30 Mar 2018 09:50
my problem is now solved!!
I have posted the complete creation of that exemplary function, so i'm unsure about what is the problematic part exactly, and why it now is solved.

Actually i assume that it may be have been unclear why "(-((x)>>31))" is the same as "(x < 0) ? 1 : 0", so i want to add that:
The "set/A" command internally uses a 32 bit signed integer datatype (signed integer means that the representation of the stored number is in two's complement). In Java and other languages this datatype is referred to as "int".
A characteristic of this reprasentation is that every bit with index >= 32 of an int is "1" if this int is negative, else "0" (but it isn't stored explicitely, because you only have 32 bits available).

When performing an "arithmetic right shift" (>>) all bits of an int value are moved to the right a given number of bit positions including the not explicitely stored bits.
Therefore if you shift a given number (n) 31 times ("x>>31"), then the result is either "11111111111111111111111111111111" (which is the representation of "-1") for negative numbers, else "00000000000000000000000000000000" (which is "0").
Negating the above result (and adding parentheses around the "x" and the result to protect against odd sideeffects) gives you the "LssZero(x)" function.

The functions aGerman has posted, are also fiddling with the bit representation of the given int numbers to compute their result.

penpen

IcarusLives
Posts: 175
Joined: 17 Jan 2016 23:55

Re: Algorithmic conditions, and returns????

#12 Post by IcarusLives » 30 Mar 2018 11:00

penpen wrote:
30 Mar 2018 10:46
IcarusLives wrote:
29 Mar 2018 19:32
My problem now lies with HOW do I write such a function? (The actual maths)? In the %getDistance% macro I posted above, it does contain somewhat of an "if" because it checks for the larger integer, but I don't know how it does that..
IcarusLives wrote:
30 Mar 2018 09:50
my problem is now solved!!
I have posted the complete creation of that exemplary function, so i'm unsure about what is the problematic part exactly, and why it now is solved.

Actually i assume that it may be have been unclear why "(-((x)>>31))" is the same as "(x < 0) ? 1 : 0", so i want to add that:
The "set/A" command internally uses a 32 bit signed integer datatype (signed integer means that the representation of the stored number is in two's complement). In Java and other languages this datatype is referred to as "int".
A characteristic of this reprasentation is that every bit with index >= 32 of an int is "1" if this int is negative, else "0" (but it isn't stored explicitely, because you only have 32 bits available).

When performing an "arithmetic right shift" (>>) all bits of an int value are moved to the right a given number of bit positions including the not explicitely stored bits.
Therefore if you shift a given number (n) 31 times ("x>>31"), then the result is either "11111111111111111111111111111111" (which is the representation of "-1") for negative numbers, else "00000000000000000000000000000000" (which is "0").
Negating the above result (and adding parentheses around the "x" and the result to protect against odd sideeffects) gives you the "LssZero(x)" function.

The functions aGerman has posted, are also fiddling with the bit representation of the given int numbers to compute their result.

penpen
penpen I would like to personally apologize for my ignorance!! You are right, I did not know about 2s compliment and bit shifting. I greatly appreciate that you took the time to explain it to me! Thank you so much. I have learned a lot from this thread, and it's brought me much joy and excitement!

IcarusLives
Posts: 175
Joined: 17 Jan 2016 23:55

Re: Algorithmic conditions, and returns????

#13 Post by IcarusLives » 03 May 2018 14:36

aGerman wrote:
30 Mar 2018 08:32

Code: Select all

@echo off &setlocal

REM ----- return 0 if false or 1 if true -----
set "LSS(x,y)=(((x-y)>>31)&1)"                     &REM <
set "LEQ(x,y)=((~(y-x)>>31)&1)"                    &REM <=
set "GTR(x,y)=(((y-x)>>31)&1)"                     &REM >
set "GEQ(x,y)=((~(x-y)>>31)&1)"                    &REM >=
set "EQU(x,y)=(((~(y-x)>>31)&1)&((~(x-y)>>31)&1))" &REM ==
set "NEQ(x,y)=((((x-y)>>31)&1)|(((y-x)>>31)&1))"   &REM !=

REM ----- values of b1 and b2 have to be either 0 or 1 -----
REM ----- return 0 if false or 1 if true -----
set "AND(b1,b2)=(b1&b2)"                           &REM &&
set "OR(b1,b2)=(b1|b2)"                            &REM ||

REM ----- ternary operation: return_value = (bool) ? value1_if_true : value2_if_false -----
REM ----- value of bool has to be either 0 or 1 -----
REM ----- returns v1 if bool=1 or v2 if bool=0 -----
set "TERN(bool,v1,v2)=((bool*v1)|((~bool&1)*v2))"  &REM ?:


REM Examples for calculations of (a > b || a < 0) ? c * -1 : c
set /a "a=-1, b=-3, c=-5"
call :calc

set /a "a=-1, b=3, c=-5"
call :calc

set /a "a=1, b=-3, c=-5"
call :calc

set /a "a=1, b=3, c=-5"
call :calc

pause
exit /b


:calc
setlocal
<nul set /p "=c = (%a% > %b% || %a% < 0) ? %c% * -1 : %c%" &echo(
set /a "x=a, y=b, b1=%GTR(x,y)%,   y=0, b2=%LSS(x,y)%,   bool=%OR(b1,b2)%,   v1=c*-1, v2=c, c=%TERN(bool,v1,v2)%"
echo c = %c%
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
endlocal &exit /b
I refrained from using logical NOT (!) in case delayed expansion matters.

Steffen
Sorry to dig this back up. I had a question. Is there an XOR using this method?

bool=%OR(b1,b2)% just means that if either b1 or b2 are 1 then %bool% = 1

Suppose I'm checking if either of them are 1, but not both.

Let me clarify...

Code: Select all

b1 = 1
b2 = 1

then bool = 1
But if what's in my head is correct, then XOR would return BOOL= 0 during this case.

Squashman
Expert
Posts: 4486
Joined: 23 Dec 2011 13:59

Re: Algorithmic conditions, and returns????

#14 Post by Squashman » 03 May 2018 14:58

So are you basically saying.
1 x 1 = 1
1 x 0 = 0

set /a bool=b1*b2

aGerman
Expert
Posts: 4678
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Algorithmic conditions, and returns????

#15 Post by aGerman » 03 May 2018 15:06

But if what's in my head is correct, then XOR would return BOOL= 0 during this case.
Correct.

Code: Select all

set "XOR(b1,b2)=((b1+b2)&1)"
The least significant bit is 0 if the result of the addition was either 0 or 2.

But Batch already supports binary XOR, hence ...

Code: Select all

set "XOR(b1,b2)=(b1^b2)"
... would have been easier.

Steffen

Post Reply