您收到的错误消息在您的情况下非常令人困惑,因为set /A 命令行中的括号是平衡的,并且如果整个命令行没有放在其括号内的代码块内自己的。无论如何,将整个 set /A 表达式放在引号之间总是一个好主意,这样括号或其他特殊字符都不会造成麻烦。
方括号对set /A 没有任何特殊意义。
无论如何,错误的根本原因是您使用小数,尽管set /A 仅支持 32 位房间中的有符号整数算术(请参阅set /? 的帮助) )。在命令提示符窗口中输入set /A (1.2*3),您将收到相同的错误消息;但删除. 一切都会好起来的。
一种可能的解决方法是使用定点算术之类的方法,因此在计算过程中将所有内容乘以 10 的整数幂,最后将结果除以 10 的相同幂,或者换句话说,移动小数点在进行计算之前指向右侧,然后将其移回。
这就是它的样子(我还在您的代码中修复了一些其他问题,但请参见下文):
@echo off
@title Calculate Caloric Needs
cls
set "name=them"
set /P "name=What is the name of the individual in question? "
:START
set "sex="
set /P "sex=Is %name% a M(ale) or F(emale)? (M/F) "
if /I not "%sex%"=="M" if /I not "%sex%"=="F" (
echo Invalid Selection... Try Again...
goto :START
)
set "w=0"
set /P "w=What is the target weight of %name%? "
set "h=0"
set /P "h=What is the height of %name% IN INCHES? "
set "h=%h%." & rem // append a decimal dot to entry in `h`
set "mil=1%h:*.=%" & rem // store everything behind first dot in `mil`, prepend `1`
set /A "h+=0, mil+=0" & rem // convert `h` to integer, dismiss fractional part
set "mil=%mil%000" & rem // pad trailing zeros to `mil`
set "mil=%mil:~,4%" & rem // extract first four numerals from `mil`
set /A "mil+=5" & rem // add `5` to `mil` for rounding
if %mil:~,1% GTR 1 set /A "h+=1" & rem // regard carry of previous addition in `h`
set "h=%h%%mil:~-3,-1%" & rem /* append second and third numeral of `mil` to `h`,
rem hence dismissing previously prepended `1`;
rem so `h` holds the height in 100ths of inches now */
set "a=0"
set /P "a=What is the age of %name%? "
rem // quotation marks avoid trouble with parenthesis or other characters;
rem /* all original constants are multiplied by `1000` to avoid fractional parts,
rem except the factor at `h` which is multiplied by `10` only due to above
rem implicit multiplication of `h` by 100, then `500` is added for rounding,
rem and finally, the result is divided by `1000` to remove the previous factors: */
if /I "%sex%"=="M" (
set /A "result=(66000+(6230*%w%)+(127*%h%)-(6800*%a%)+500)/1000"
) else if /I "%sex%"=="F" (
set /A "result=(655000+(4350*%w%)+(47*%h%)-(4700*%a%)+500)/1000"
)
echo %result% is the caloric intake for %name%.
pause
exit /B
这是我修复的:
- 改进了
set 和set /P 语法,使整个表达式位于引号之间,因此您避免了特殊字符的麻烦,并且您可以清楚地看到是否有任何尾随空格;
- 任何提示值都会被初始化,以避免在用户只是按下 RETURN 的情况下使用之前的值;
- 对性别输入的
if 查询进行了更正,现在通过添加开关/I,它们不区分大小写,并且通过将比较表达式括在引号中,它们不会在测试变量为空的情况下造成麻烦;
顺便说一句,你可能对 choice 命令感兴趣,因为它甚至不接受任何其他字符;
- 高度条目
h 的英寸值由于上述定点算法被转换为英寸的百分之一(但重量w 和年龄a 仍被视为整数);这是它的工作原理:
-
set "h=%h%.":在h 中的条目上附加一个点,以确保至少有一个;
-
set "mil=1%h:*.=%":将h 中第一个点之后的所有内容存储到mil(小数部分)中,并在结果前面加上1,以免丢失任何前导零(这对于小数部分很重要)转换为数字;
-
set /A "h+=0, mil+=0":将h 和mil 都转换为数值(整数);这会将直到第一个非数字数字的所有内容都转换为数字,忽略前导空格,但考虑符号 +/-(尽管它们不相关,因为这里不需要);
-
set "mil=%mil%000":将 3 个尾随零添加到小数部分(前面的 1 仍然存在,因此始终至少有 4 个数字);
-
set "mil=%mil:~,4%":提取前 4 个字符(所以前面的 1 再加上 3 个数字);
-
set /A "mil+=5":加上5,所以如果最后一个数字是5或更多,就会出现进位,所以倒数第二个数字会向上取整;
-
if %mil:~,1% GTR 1 set /A "h+=1":在h 中增加整数部分,以防进位超过小数部分;
-
set "h=%h%%mil:~-3,-1%":将h的整数部分与mil中小数部分的倒数第二个数字的范围连接起来,存储在h中;
-
result 公式中的所有常数都乘以1000 使小数点消失,除了h 的因子仅乘以10,因为h 已经是100 次原始高度值;之后结果除以1000;添加500 仅意味着在除以1000 时添加0.5,并且旨在将小数部分从.5 向上舍入到.9*,以免因整数除法而丢失;李>
-
exit 命令被替换为exit /B 以终止批处理文件而不是拥有的cmd 实例;
请注意,像 // 和 /*、*/ 这样的 cmets 在批处理文件中没有特殊含义。评论或评论由rem 声明给出。我在这里使用了rem 中的斜杠样式的 cmets,只是为了在此站点上突出显示一些很酷的语法...
更新
根据comment by the original poster,结果本身应该是一个小数,所以我稍微修改了脚本(下面是描述):
@echo off
@title Calculate Caloric Needs
cls
set "name=them"
set /P "name=What is the name of the individual in question? "
set "male="
choice /C MF /M "Is %name% a M(ale) of F(emale)? "
if not ErrorLevel 2 set "male=Flag"
set "w=0"
set /P "w=What is the target weight of %name% IN POUNDS? "
set "h=0"
set /P "h=What is the height of %name% IN INCHES? "
set "h=%h%." & rem // append a decimal dot to entry in `h`
set "mil=1%h:*.=%" & rem // store everything behind first dot in `mil`, prepend `1`
set /A "h+=0, mil+=0" & rem // convert `h` to integer, dismiss fractional part
set "mil=%mil%000" & rem // pad trailing zeros to `mil`
set "mil=%mil:~,4%" & rem // extract first four numerals from `mil`
set /A "mil+=5" & rem // add `5` to `mil` for rounding
if %mil:~,1% GTR 1 set /A "h+=1" & rem // regard carry of previous addition in `h`
set "h=%h%%mil:~-3,-1%" & rem /* append second and third numeral of `mil` to `h`,
rem hence dismissing previously prepended `1`;
rem so `h` holds the height in 100ths of inches now */
set "a=0"
set /P "a=What is the age of %name% IN YEARS? "
rem // quotation marks avoid trouble with parenthesis or other characters;
rem /* all original constants are multiplied by `1000` to avoid fractional parts,
rem except the factor at `h` which is multiplied by `10` only due to above
rem implicit multiplication of `h` by 100, then `500` is added for rounding,
rem and finally, the result is divided by `1000` to remove the previous factors: */
if defined male (
set /A "result=66000+(6230*%w%)+(127*%h%)-(6800*%a%)+5"
) else (
set /A "result=655000+(4350*%w%)+(47*%h%)-(4700*%a%)+5"
)
echo %result:~,-3%.%result:~-3,-1% is the caloric intake for %name%.
pause
exit /B
这就是我所做的:
- 基本计算公式还是一样的,只是这次省略了
1000的除法,将5加到结果中进行四舍五入,而不是500;但是,为了显示结果,最后一个数字被忽略,并在剩余的最后两个数字之前插入一个小数点 .,因此结果有两个小数位;
- 性别输入现在由
choice 命令完成,如该答案的原始版本中所建议(见上文),因此不再需要捕获无效结果,因为choice 只接受预定义的键或字符;