I have a batch file which must be able to display a percentage. Unfortunately I have no idea how to accomplish this.
The file takes a range of individual points from 0 to 29 and adds or subtracts points from this range in a background process the user never sees. I want the current percent of how full that range is to be displayed. IE if there are 29 points the file displays "100 %", if there are 22 points it lists "75 %", ectra.
Mathematically the operation should be (x/29)*100. I have coded this operation as:
set /a math="%shields%" / "%scap%"
set /a sm="%math%" * 100
but my code dose not function. sm is the variable which will be the percent, shields is the current 0 - 29 point value and scap is the maximum value shields can be (normally 29 but some conditions can adjust this.)
Can I get a hand with this please? Its confusing.
Matematic operation in bat don't accept floating point value if you make :
22/29 in bat you'll get 0 and 0 *100 = 0.
so you have to do (x*100)/29
#echo off
set $val=22
set /a $percent=(%$val%*100)/29
echo %$percent% %%
Related
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.
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.
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)
I am making a batch rpg game, and am working on a shop. You are supposed to be able to upgrade your weapons/armor, and i would like to know how to make a way so the price increases when you buy. Heres what i have:
if %money% GEQ (%WeaponLevel% * 4) / 2 then set money=(%WeaponLevel% * 4) / 2 & set WeaponLevel=%WeaponLevel% + 1
Thanks! Hope i'm not too far off :)
set /a $=money - (weaponlevel *2)
if %$% geq 0 set /a money=$&set /a weaponlevel +=1
Using a temporary variable $ (its name is not relevant - but don't use the reserved names temp or tmp),
set the tempval to money-(weaponlevel*2)
Note that in set/a, the variablenames do not need to be enclosed in %. Also that ((%weaponlevel% * 4) / 2) is exactly the same as (weaponlevel*2)
if the resultant temporary value is greater than or equal to zero, then change the values of money and weaponlevel using set /a; the new value of money is in the temporary variable and +=1 increments a value.
You could try:
rem My weapon upgrade script
set price=weaponlevel * 4
set /a money-= %price%
Run that script whenever the player goes to upgrade the weapon and the price will be equal to the weapon level * 4 everytime and will reduce the money by that set price. I hope this help : D
I am a new comer to programming in COBOL and I am having difficulty at something that probably should be trivial. I am wanting to find the min and max of what the user enters. When the user hits 0 the max, min, and avg should display. The avg is easy but the min and max had me wondering. If this was JAVA or another lang I'd just do some scenario with comparing MAX INT value. Unfortunately High-Value and Low-Value in COBOL are not Integer values???? So I decided to put the user's entries in a table and then use the intrinsic functions to do what I need. However as soon as I attempt to compute like this:
compute Min-Result = Function Min (Num-Field(ALL))
I get an error that says, "syntax error, unexpected all." I am totally confused at this point on what to do and why I get this error. I am using OpenCOBOL 1.1 Mingw. Here is my complete code. Any help would be greatly appreciated. Anything at all. I also made sure no lines were over 72.
identification division.
program-id. lab1a.
* no envionrment division since there are no files needed, etc.
data division.
working-storage section.
* declaring proper variables to store integer values
01 Max-Result PIC S9(5).
01 Min-Result PIC S9(5).
01 Count-Val PIC 9 Value 0.
01 Running-Tot PIC S9(10)v99.
01 First-Zero PIC 9 Value 1.
01 Final-Format-Avg PIC ZZZZZ9.9999.
01 Avg-Ent PIC S9(5)v9999.
01 Calc-Table.
03 Table-Record Occurs 1 to 500 times
depending on Entered-Num.
05 Num-Field PIC S9(5).
01 Entered-Num PIC S9(5).
procedure division.
000-Main.
perform with test after until Entered-Num = 0
display "Enter a 4-digit number (0 to stop): "
with no advancing
accept Entered-Num
add 1 to Count-Val
add Entered-Num to Running-Tot
display Running-Tot
display Count-Val
move Entered-Num to Num-Field(Count-Val)
* this way every time the user enters a non zero number it will be re-assigned
* to the variable Ending-Num. If they enter zero the if condition is skipped, the
* loop condition is tested at the top and is ended.
end-perform.
subtract 1 from Count-Val
display Count-Val
display " "
display " "
*WATCH FOR TRUNCATION ERROR.....
Divide Running-Tot By Count-Val Giving Avg-Ent
move Avg-Ent to Final-Format-Avg
*******WHY DOES THIS NOT WORK???????***********************
compute Min-Result = Function Min (Num-Field(ALL))
compute Max-Result = Function Max (Num-Field(ALL))
if First-Zero = 0
display "The first number you entered was zero.
& Next time enter a different one."
else
display "The lowest value entered: " Min-Result
display "The highest value entered: " Max-Result
display "The average value entered: "
Final-Format-Avg
end-if
stop run.
ALL is not currently supported for OpenCOBOL intrinsics, which is a feature that is on the the books for implementation.
You have "Entered-Num" as your Occurs Depending On field. Entered-Num by the time you use the function is zero. It should be Count-Val.
That's not the problem, but you asked.
Look at a 2009 OpenCobol Programmer's Guid, I can find no confirmation that ALL is supported.
It will be much simpler/faster to keep a "lowest value" and a "highest value" and compare to/replace as necessary with the entered number.