Page 1 of 2

Algorithmic conditions, and returns????

Posted: 29 Mar 2018 15:44
by IcarusLives
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!

Re: Algorithmic conditions, and returns????

Posted: 29 Mar 2018 16:32
by aGerman
You're looking for logical operators.
That topic provides a workaround:
viewtopic.php?f=3&t=4308

Steffen

Re: Algorithmic conditions, and returns????

Posted: 29 Mar 2018 16:57
by IcarusLives
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.

Re: Algorithmic conditions, and returns????

Posted: 29 Mar 2018 17:28
by aGerman
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

Re: Algorithmic conditions, and returns????

Posted: 29 Mar 2018 19:03
by penpen
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

Re: Algorithmic conditions, and returns????

Posted: 29 Mar 2018 19:32
by IcarusLives
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..

Re: Algorithmic conditions, and returns????

Posted: 29 Mar 2018 19:33
by Aacini
Perhaps this thread may help you.

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

Antonio

Re: Algorithmic conditions, and returns????

Posted: 29 Mar 2018 19:51
by IcarusLives
Aacini, this is brilliant! Thank you for sharing!!!

Re: Algorithmic conditions, and returns????

Posted: 30 Mar 2018 08:32
by aGerman

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

Re: Algorithmic conditions, and returns????

Posted: 30 Mar 2018 09:50
by IcarusLives
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!

Re: Algorithmic conditions, and returns????

Posted: 30 Mar 2018 10:46
by penpen
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

Re: Algorithmic conditions, and returns????

Posted: 30 Mar 2018 11:00
by IcarusLives
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!

Re: Algorithmic conditions, and returns????

Posted: 03 May 2018 14:36
by IcarusLives
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.

Re: Algorithmic conditions, and returns????

Posted: 03 May 2018 14:58
by Squashman
So are you basically saying.
1 x 1 = 1
1 x 0 = 0

set /a bool=b1*b2

Re: Algorithmic conditions, and returns????

Posted: 03 May 2018 15:06
by aGerman
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