Arithmetic inside Round brackets leads to Missing operand

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
BoQsc
Posts: 80
Joined: 30 Jun 2014 04:10

Arithmetic inside Round brackets leads to Missing operand

#1 Post by BoQsc » 13 Mar 2020 09:19

I tried to use arithmetic inside IF statement

Code: Select all

		SET "Result=8"
		SET /A "Result=%Result% * 2"
		echo %Result% asdfghjkl
and I've got error saying Missing operand I wonder if I need to EnableDelayedExpansion for arithmetic to work inside the IF statement

Full script

Code: Select all

@ECHO OFF
REM Get current Year and Month for Windows 10
set "year_now=%date:~2,2%";
set "month_now=%date:~5,2%";

echo %year_now% 
echo %month_now%

set "releaseCycle=Interim";
IF "%releaseCycle%"=="LTS" (
	echo useful
) ELSE IF "%releaseCycle%"=="Interim" (
	IF %month_now% LSS 04 (

		SET "Result=8"
		SET /A "Result=%Result% * 2"
		echo %Result% asdfghjkl
	)
  echo interim here
) ELSE IF "%releaseCycle%"=="Daily" (
	echo useful
) ELSE (
	echo useful
)


pause
Output:

Code: Select all

20
03
Missing operand.
 asdfghjkl
interim here

dbenham
Expert
Posts: 2347
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Arithmetic inside Round brackets leads to Missing operand

#2 Post by dbenham » 13 Mar 2020 09:52

SET /A is the one case where you don't need delayed expansion because SET /A can expand variables directly - there is no need to use % or ! expansion.

Code: Select all

set /a "result=result*2"
:: or better yet
set /a "result*=2"
But why do you initially set result to 8 in the first place?
why not

Code: Select all

set /a "result=8*2"
:: or simply
set "result=16"
But your ECHO statement must use delayed expansion because it is within the IF block that sets the variable
You will need SETLOCAL EnableDelayedExpansion somewhere earlier in your script, and then

Code: Select all

echo !result! asdfghjkl
But honestly with your simple example I would have

Code: Select all

set "result=16"
echo 16
Though I suppose your script is not really functional, and designed just to demo an issue.


Dave Benham

BoQsc
Posts: 80
Joined: 30 Jun 2014 04:10

Re: Arithmetic inside Round brackets leads to Missing operand

#3 Post by BoQsc » 13 Mar 2020 10:09

dbenham wrote:
13 Mar 2020 09:52
SET /A is the one case where you don't need delayed expansion because SET /A can expand variables directly - there is no need to use % or ! expansion.

Code: Select all

set /a "result=result*2"
:: or better yet
set /a "result*=2"
But why do you initially set result to 8 in the first place?
why not

Code: Select all

set /a "result=8*2"
:: or simply
set "result=16"
But your ECHO statement must use delayed expansion because it is within the IF block that sets the variable
You will need SETLOCAL EnableDelayedExpansion somewhere earlier in your script, and then

Code: Select all

echo !result! asdfghjkl
But honestly with your simple example I would have

Code: Select all

set "result=16"
echo 16
Though I suppose your script is not really functional, and designed just to demo an issue.


Dave Benham
You are correct, that' s just a simplification and demonstration.

I guess I won't avoid using EnableDelayedExpansion in this kind of script.

Thank you.

BoQsc
Posts: 80
Joined: 30 Jun 2014 04:10

Arithmetic operation is successful but "Missing operator." is displayed in the output

#4 Post by BoQsc » 13 Mar 2020 11:47

Code: Select all

@ECHO OFF
SETLOCAL EnableDelayedExpansion

REM Get current Year and Month for Windows 10
SET "year_now=%date:~2,2%";
SET "month_now=%date:~5,2%";

SET "releaseCycle=Interim";
IF "%releaseCycle%"=="LTS" (
	echo "Haven't been implemented";
) ELSE IF "%releaseCycle%"=="Interim" (
	IF %month_now% LSS 04 (
		echo ----Here----
		SET /A "year=!year_now! - 1";
		echo ----Here----
		SET "release_version=!year!.10"
		echo !release_version!;
	)
	IF %month_now% LSS 10 (
		IF %month_now% GEQ 04 (
			SET "release_version=!year_now!.04"
			echo !release_version!;
		)
	)
	IF %month_now% GEQ  10 (
		SET "release_version=!year_now!.10"
		echo !release_version!;
	)
) ELSE IF "%releaseCycle%"=="Daily" (
	echo "Haven't been implemented";
) ELSE (
	echo "Haven't been implemented";
)
pause
Output:

Code: Select all

----Here----
Missing operator.
----Here----
19.10;

dbenham
Expert
Posts: 2347
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Arithmetic inside Round brackets leads to Missing operand

#5 Post by dbenham » 13 Mar 2020 13:09

FYI - No need to create a separate topic when this last question is obviously related to the previous.

The ; at the end of the statement is causing the problem. SET /A sort of is expecting a second computation, although the proper symbol to use for multiple computations is a comma. Remove the semicolon and it works without error.

Why are you still explicitly expanding the variable? It works, but as I showed in my last post, that is not needed when using SET /A. You could use SET /A "YEAR=YEAR_NOW - 1"

Your way of dealing with dates is not good as it depends on the locale settings for the computer. For example, %date% on my machine yields Fri 03/13/2020 which completely breaks your code.

You should be using FOR /F with WMIC OS GET LOCALDATETIME to get the date and/or time in a way that can be parsed reliably. There is another WMIC option to get the various date/time components separately, but I cannot remember off the top of my head.

Your SET /A arithmetic will fail when you get a number like 08 or 09 because 0 prefixed values are treated as octal notation. A simple solution is to prefix the value with 1 and then subtract 100.
For example:

Code: Select all

set month=09
set /a "PrevMonth=1%month%-100"
Note that in this case you must explicitly expand the month value to get the correct result. SET /A "PREVMONTH=1MONTH-100" will NOT work.


Dave Benham

BoQsc
Posts: 80
Joined: 30 Jun 2014 04:10

Re: Arithmetic inside Round brackets leads to Missing operand

#6 Post by BoQsc » 13 Mar 2020 14:46

dbenham wrote:
13 Mar 2020 13:09
Why are you still explicitly expanding the variable? It works, but as I showed in my last post, that is not needed when using SET /A. You could use SET /A "YEAR=YEAR_NOW - 1"
dbenham wrote:
13 Mar 2020 13:09
Note that in this case you must explicitly expand the month value to get the correct result. SET /A "PREVMONTH=1MONTH-100" will NOT work.
I do believe you answered that yourself.
I just though that it will relieve the mental-load while reading and understanding that part of script.


dbenham wrote:
13 Mar 2020 13:09
FYI - No need to create a separate topic when this last question is obviously related to the previous.
Understood, won't happen again. :D
dbenham wrote:
13 Mar 2020 13:09
The ; at the end of the statement is causing the problem. SET /A sort of is expecting a second computation, although the proper symbol to use for multiple computations is a comma. Remove the semicolon and it works without error.
That's a mild mistake of mine, I'm glad I didn't put ; at the end of every statement.
Although would have helped to figure out the cause of this on my own. :idea:

dbenham wrote:
13 Mar 2020 13:09
Your way of dealing with dates is not good as it depends on the locale settings for the computer. For example, %date% on my machine yields Fri 03/13/2020 which completely breaks your code.

You should be using FOR /F with WMIC OS GET LOCALDATETIME to get the date and/or time in a way that can be parsed reliably. There is another WMIC option to get the various date/time components separately, but I cannot remember off the top of my head.
I would like to know if that's Windows 10 that you are using or one of the deprecated versions: Windows 8.1, Windows 8, Windows 7, Windows vista, Windows xp?
I'm kind of aware of this, but it is great that you pointed out. If the problem with date representation appears on Windows 10 I might consider WMIC.
However for simplicity I would like to keep using this method of gathering Date from operating system.
Not to mention that this is a port from Bash script to Batch script. I would like to keep both looking similarly for cross-platform readability if that's possible.

dbenham wrote:
13 Mar 2020 13:09
Your SET /A arithmetic will fail when you get a number like 08 or 09 because 0 prefixed values are treated as octal notation. A simple solution is to prefix the value with 1 and then subtract 100.
For example:

Code: Select all

set month=09
set /a "PrevMonth=1%month%-100"
Dave Benham
Now this is really great observation, would have not though about this until it has been too late.

Thanks Dave, will try to implement these changes tomorrow.

dbenham
Expert
Posts: 2347
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Arithmetic inside Round brackets leads to Missing operand

#7 Post by dbenham » 13 Mar 2020 15:08

BoQsc wrote:
13 Mar 2020 14:46
dbenham wrote:
13 Mar 2020 13:09
Your way of dealing with dates is not good as it depends on the locale settings for the computer. For example, %date% on my machine yields Fri 03/13/2020 which completely breaks your code.

You should be using FOR /F with WMIC OS GET LOCALDATETIME to get the date and/or time in a way that can be parsed reliably. There is another WMIC option to get the various date/time components separately, but I cannot remember off the top of my head.
I would like to know if that's Windows 10 that you are using or one of the deprecated versions: Windows 8.1, Windows 8, Windows 7, Windows vista, Windows xp?
I'm kind of aware of this, but it is great that you pointed out. If the problem with date representation appears on Windows 10 I might consider WMIC.
However for simplicity I would like to keep using this method of gathering Date from operating system.
Not to mention that this is a port from Bash script to Batch script. I would like to keep both looking similarly for cross-platform readability if that's possible.
The issue most definitely is persistent across all versions of Windows - All versions of Windows have configuration settings to control the format of %DATE% for different locales.

WMIC is universally available to all versions of Windows from Vista onward. Some versions of XP do not have WMIC, but hopefully you are not still dealing with machines that are still on XP, given that it has not been supported since April 2014.


Dave Benham

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

Re: Arithmetic inside Round brackets leads to Missing operand

#8 Post by Squashman » 13 Mar 2020 21:40

Windows 8 is not deprecated.

BoQsc
Posts: 80
Joined: 30 Jun 2014 04:10

Re: Arithmetic inside Round brackets leads to Missing operand

#9 Post by BoQsc » 14 Mar 2020 10:29

Squashman wrote:
13 Mar 2020 21:40
Windows 8 is not deprecated.
Windows 8
Unsupported as of January 12, 2016
https://en.wikipedia.org/wiki/Windows_8

Windows 8.1
Mainstream support ended on January 9, 2018
Extended support until January 10, 2023
Upgrading to Windows 8.1 is required for Windows 8 users to receive updates and support after January 12, 2016[4]
https://en.wikipedia.org/wiki/Windows_8.1

Officialy might be deprecated in 3 years. I consider them already deprecated. Since all the encouragement is towards windows 10.
https://en.wikipedia.org/wiki/Deprecation

BoQsc
Posts: 80
Joined: 30 Jun 2014 04:10

Re: Arithmetic inside Round brackets leads to Missing operand

#10 Post by BoQsc » 14 Mar 2020 11:12

dbenham wrote:
13 Mar 2020 13:09
Your way of dealing with dates is not good as it depends on the locale settings for the computer. For example, %date% on my machine yields Fri 03/13/2020 which completely breaks your code.

You should be using FOR /F with WMIC OS GET LOCALDATETIME to get the date and/or time in a way that can be parsed reliably. There is another WMIC option to get the various date/time components separately, but I cannot remember off the top of my head.
This one should resolve both octal notation problem and inconsistencies of parsing date across different Windows versions.
I'm sharing to make sure I'm not missing something.

Code: Select all

@echo off
SETLOCAL EnableDelayedExpansion

FOR /F "skip=1 tokens=1-6" %%A IN ('WMIC Path Win32_LocalTime Get Day^,Hour^,Minute^,Month^,Second^,Year /Format:table') DO (
    SET "YEAR=!YEAR!%%F"
    SET "MONTH=!MONTH!%%D"
    SET "DAY=!DAY!%%A"

 )


echo YEAR %YEAR% 
echo MONTH %MONTH% 
echo DAY %DAY% 
Output:

Code: Select all

YEAR 2020
MONTH 3
DAY 14

BoQsc
Posts: 80
Joined: 30 Jun 2014 04:10

Re: Arithmetic inside Round brackets leads to Missing operand

#11 Post by BoQsc » 14 Mar 2020 11:43

And here the main script with the new method of gathering date from operating system: Seems to be working pretty well.

Code: Select all

@ECHO OFF
SETLOCAL EnableDelayedExpansion

REM Get current Year and Month for Windows 10 Windows 8.1 Windows 8 Windows 7
FOR /F "skip=1 tokens=1-6" %%A IN ('WMIC Path Win32_LocalTime Get Day^,Hour^,Minute^,Month^,Second^,Year /Format:table') DO (
    SET "year_now=!year_now!%%F"
    SET "month_now=!month_now!%%D"

 )
SET "year_now=%year_now:~2,2%"


SET "releaseCycle=Interim";
IF "%releaseCycle%"=="LTS" (
	echo "Haven't been implemented";
) ELSE IF "%releaseCycle%"=="Interim" (
	IF %month_now% LSS 4 (
		SET /A "year=!year_now! - 1"
		SET "release_version=!year!.10"
		echo !release_version!;
	)
	IF %month_now% LSS 10 (
		IF %month_now% GEQ 04 (
			SET "release_version=!year_now!.04"
			echo !release_version!;
		)
	)
	IF %month_now% GEQ  10 (
		SET "release_version=!year_now!.10"
		echo !release_version!;
	)
) ELSE IF "%releaseCycle%"=="Daily" (
	echo "Haven't been implemented";
) ELSE (
	echo "Haven't been implemented";
)
pause

Code: Select all

19.10;
Press any key to continue . . .

Post Reply