Handling Negative Decimal in Batch - batch-file

Mine is a very simple code - I'm looking to find out if the difference between a couple of dates gives negative or not. Problem is not in getting the value, but in checking if they're negative or not. Here's my code:
if !val! LSS 0 (
echo value is !val!
echo value is less than zero - SLA breached!
) else (
echo value is !val!
echo value is greater than zero - SLA not breached.
)
The values of !val! are:
-0.9513888888888888888888888888888888888889
63.06736111111111111111111111111111111111
-1.09722222222222222222222222222222222222
-1.19236111111111111111111111111111111111
First two results are fine - no issues in detecting they're positive and negative. Next two - batch says that they're greater than one! Here's the result:
value is -.95138889
value is less than zero - SLA breached
value is 63.0673611
value is greater than zero - SLA not breached.
value is -1.1923611
value is greater than zero - SLA not breached.
value is -1.0972222
value is greater than zero - SLA not breached.
Where am I going wrong?

I found a different way to approach this -
if "!val:~0,1!"=="-" (
echo value is !val!
echo value is less than zero - SLA breached!
) else (
echo value is !val!
echo value is greater than zero - SLA not breached.
)
Here's the result:
value is 63.0673611
value is greater than zero - SLA not breached.
value is -.95138889
value is less than zero - SLA breached
value is -1.0972222
value is less than zero - SLA breached
value is -1.1923611
value is less than zero - SLA breached
Hope this helps someone!

Related

How can I replace all instances of a letter and decimal combination greater than a predefined value

I am trying to search through text and find every instance of "Z" followed by a number. If the number is 40 or higher, then it will be replaced with 32.
So for example
N170G00Z58
N280G81X9.1787Y15.1981Z2.3803R4.6F.75L0.0
N300G00Z15.0
N580G03X-12.125Y6.7311Z52.775I-12.5J6.7311F35.0
Would produce
N170G00Z32
N280G81X9.1787Y15.1981Z2.3803R4.6F.75L0.0
N300G00Z15.0
N580G03X-12.125Y6.7311Z32I-12.5J6.7311F35.0
We are only looking at and changing the Z values.
I have tried with the following code, but it removes all Z values instead.
the "%VarOne%%MS201%" is just the file I have previously output, that I am using as a source.
set "INTEXTFILE=%VarOne%%MS201%"
for /f "delims=Z*" %%a in ('type "%INTEXTFILE%"') do (
SET s=%%a
IF s GTR Z40 SET s=!s:Z32!
echo !s!>>new.txt
)
I need to do this with other values as well (any Y value over 40 needs changed to "Y40"), so hopefully, the solution is expandable and understandable by me. I am fully aware that I do not fully know what I am doing, but I am trying.
One possible solution is using the batch/JScript hybrid JREPL.BAT with the command line:
call "%~dp0jrepl.bat" "Z(?:[1-9][0-9]{2,}|[4-9][0-9])(?:\.[0-9]+)?" "Z32" /F "%VarOne%%MS201%" /O New.txt
There could be used - instead of New.txt to do the replaces directly in file with name defined by %VarOne%%MS201%.
jrepl.bat is referenced here with the path of the batch file containing this command line and the definitions of the environment variables VarOne and MS201 which means jrepl.bat must be in same directory as the batch file.
The search expression Z(?:[1-9][0-9]{2,}|[4-9][0-9])(?:\.[0-9]+)? means:
Z ... find first case-sensitive this letter.
(?:...) ... is a non-marking group used here for an OR expression.
[1-9][0-9]{2,} ... there must be after Z a digit in range 1 to 9 with at least two or more digits in range 0 to 9. So this expression matches numbers in range 100 to 999999999 and even higher numbers.
| ... means OR as a second expression is needed for numbers lower than 100 after Z.
[4-9][0-9] ... matches a number with exactly two digits whereby the first digit must be in range 4 to 9 and the second digit can be in range 0 to 9. So this expression matches numbers in range 40 to 99.
(?:...)? ... that is once again a non-marking group used here to apply the multiplier ? on the entire expression inside the group which means applied zero or exactly once. In other words the expression inside this group with multiplier ? matches optionally also a string.
\.[0-9]+ ... matches a dot escaped with a backslash to be interpreted as literal character and one or more digits in range 0 to 9. This optionally applied expression matches the decimal point and the post comma digits of a floating point value.
For a replacement of all Z values with value 32 or higher the group with the OR expression must be extended by one more expression:
call "%~dp0jrepl.bat" "Z(?:[1-9][0-9]{2,}|[4-9][0-9]|3[2-9])(?:\.[0-9]+)?" "Z32" /F "%VarOne%%MS201%" /O New.txt
|3[2-9] ... is a third OR expression matching numbers in range 32 to 39.
So the three expressions in the OR group match numbers 100 or higher, 40 to 99 and 32 to 39 as integers or as floating point values with a decimal point and one or more decimal places with the optionally applied expression in second non-marking group.

If greater than in batch files [duplicate]

This question already has an answer here:
Windows batch file IF failure - How can 30000000000000 equal 40000000000?
(1 answer)
Closed 5 years ago.
I have a very silly issue but unable to figure out what is wrong
I'm doing a basic level number comparison in if statement. script is pasted below. geq-greater than or equal to is working fine but gtr-greater than has a problem. Is there any limitation for numbers in gtr comparison?
if 3 gtr 2 (#echo "greater") else (#echo "lesser")
greater
if 3 geq 2 (#echo "greater") else (#echo "lesser")
greater
if 135149772801 gtr 111110000000 (#echo "greater") else (#echo "lesser")
lesser
if 135149772801 geq 111110000000 (#echo "greater") else (#echo "lesser")
greater
Is there any limitation for numbers in gtr comparison?
Yes, there really is.
You're limited to 32-bit signed integers and, if there's overflow, it's set to the maximum value.
Since both those numbers, 135149772801 and 111110000000, are too big, they're both converted to 231 - 1.
That's why it says the first is not greater (which is subtly different to lesser, by the way) but it is greater than or equal to.
More details can be found at the excellent dostips site.
A way around the 32-bit limit is to prefix the numeric-string with a goodly number of 0 and then use an alphabetic comparison on the last n characters.
Hence
set "num1=135149772801"
set "num2=111110000000"
set "zeroes=00000000000000000000000000000000000000000000000000000"
set "comp1=%zeroes%%num1%"
set "comp2=%zeroes%%num2%"
if "%comp1:~-20%" gtr "%comp2:~-20%" (echo greater) else (echo not greater)
where "-20" above means "take the last 20 characters"
A batch-file natively supports 32-bit signed integer arithmetic only. If the number goes over 2147483648, it overflows and warp back to negative number. However in if statements, the number gets clutter back to 2^31-1.
Code | Code Result | Actual Result
-----------------------+-------------------+-----------------------
2147483647 + 1 2147483648 2147483648
2147483648 + 1 -2147483648 2147483649
Here is some possible workaround:
Chopping the number(making the number smaller before comparing)
Other scripting languages(use powershell or vbs to compare)
Embedded Powershell solution:
for /f %p in ('powershell -command if (1 -gt 0^) {write-host greater} else {write-host lesser}') do echo %p
This command calls powershell to compare, and retrieve the results using a for loop.

Simple IF statement with more than 1 digit numbers?

Below I'm testing a simple IF statement but it doesn't seem to take the whole number I'm comparing in to account. You can see this number is greater than "2", but with my result it's like it's only reading the "1" and that's it, so telling me the number is "Less or Equal" than "2", I would expect the result "LARGE" to be returned. How can I get it to read the whole number and not just the first digit?
IF "1073740972" LEQ "2" (
ECHO LESS or EQU 2
) ELSE (
ECHO LARGE
)
The "LARGE" number is an %ERRORLEVEL% generated number so this can be different each time.
I have tried Changing [LEQ "2"] to [LSS "3"] but I do not know what else I could try.
Thanks in advance
Remove the quotation marks from the comparison expressions:
IF 1073740972 LEQ 2 (
ECHO LESS or EQU 2
) ELSE (
ECHO LARGE
)
Otherwise, no numeric but string comparison is performed, where the character codes are regarded, so character 1 (ASCII 49 = 0x31) is less than character 2 (ASCII 50= 0x32).

Batch - Multiple commands if button press

I'm coding a simple game and needed help,
pcash = user cash
reshp1 = cost to restore hp
php = player health
How do I write these into 1 line?
If user press 1, check if cash is equal or greater to the cost of restore hp, if it is greater - subtract cash base on cost of restore hp, then finally add the hp by 20%.
This is what I have tried, but did not work as expected.
if "%restorer%"=="1" if %pcash% geq %reshp1c% && set /a pcash=%pcash% - %reshp1c% && set /a php=%php% * .20
if "%restorer%"=="1" if %pcash% geq %reshp1c% set /a pcash=%pcash% - %reshp1c%&set /a php=%php%*6/5
& is used to separate cascaded statement. Batch uses integer mathematics, so *6/5 will multiply by 6 then divide by 5, adding 20% to the prior value (your code, had it worked, would have set the value to 20% of its prior magnitude)

What roles do minus signs and single quotation marks play in if statements?

In the following code, adding the same letter to both operands of the comparison changes the result. Despite - being not greater than j, -k is greater than jk.
This only happens if one of the operands is the minus sign (-) or single quotation mark (').
Why does this happen? What are the rules?
if - gtr j (echo - greater than j) else echo - less than j
if "-" gtr "j" (echo "-" greater than "j") else echo "-" less than "j"
echo.
if -k gtr jk (echo -k greater than jk) else echo -k less than jk
if "-k" gtr "jk" (echo "-k" greater than "jk") else echo "-k" less than "jk"
echo.
if ' gtr u (echo ' greater than u) else echo ' less than u
if "'" gtr "u" (echo "'" greater than "u") else echo "'" less than "u"
echo.
if 'v gtr uv (echo 'v greater than uv) else echo 'v less than uv
if "'v" gtr "uv" (echo "'v" greater than "uv") else echo "'v" less than "uv"
The result is:
- less than j
"-" less than "j"
-k greater than jk
"-k" greater than "jk"
' less than u
"'" less than "u"
'v greater than uv
"'v" greater than "uv"
You may be assuming that strings are just compared character by character, taking their ordinal values.
That's not true. Collation is much more complex than that.
In fact, you can see the same in other environments, such as Windows PowerShell:
PS Home:\> '-' -gt 'j'
False
PS Home:\> '-k' -gt 'jk'
True
PS Home:\> '''' -gt 'u'
False
PS Home:\> '''v' -gt 'uv'
True
It could very well be that the order of strings varies with your locale as well.
As for your particular problem here, quoting from the Unicode Collation Algorithm (UTS #10):
Collation order is not preserved under concatenation or substring operations, in general.
For example, the fact that x is less than y does not mean that x + z is less than y + z, because characters may form contractions across the substring or concatenation boundaries. In summary:
x < y does not imply that xz < yz
x < y does not imply that zx < zy
xz < yz does not imply that x < y
zx < zy does not imply that x < y
and to solve the misconveption you're likely under:
Collation is not code point (binary) order.
A simple example of this is the fact that capital Z comes before lowercase a in the code charts. As noted earlier, beginners may complain that a particular Unicode character is “not in the right place in the code chart.” That is a misunderstanding of the role of the character encoding in collation. While the Unicode Standard does not gratuitously place characters such that the binary ordering is odd, the only way to get the linguistically-correct order is to use a language-sensitive collation, not a binary ordering.

Resources