标题: [数值计算] 看起来正常计算的两个数,批处理结果怎么变成了负数? [打印本页]
作者: zds612 时间: 2018-10-30 14:05 标题: 看起来正常计算的两个数,批处理结果怎么变成了负数?
各位,我写了个用于监视磁盘容量的小代码,刚开始测试还正常,多试几次之后就异常了
现象是,在xp下,通过dir+for获取到磁盘剩余字节,除以1048576(转为MB单位)
结果为负数了。。如图:
在win7环境下,计算结果为0,提示:无效数字,无效数字。数字精确度限为 32 位。
如图:
请大家帮忙看看是什么问题,谢谢!
贴代码:- @echo off
- mode con cols=50 lines=10
- color 0a
- Title -[磁盘检测程序(自动电邮告警)]
- set log_file_name=RunLog.txt
- set lineno_max=365
- set avail=1000
- set svrname="测试服务器"
- set ipaddr="192.168.180.000"
- set freesize=0
- set num=1048576
- set disk1=c
-
- if NOT exist %log_file_name% (echo 执行日志:>%log_file_name%)
- for /f "delims=:" %%a in ('findstr/n .* "%log_file_name%"') do set lineno=%%a
- echo %log_file_name%文件共有%lineno%行
- if %lineno% GTR %lineno_max% (echo 执行日志:>%log_file_name% && echo %log_file_name%文件已经清空!)
-
- for /f "tokens=3 delims= " %%a in ('dir /-c %disk1%:') do set "mc=%%a"
- echo %mc%字节
- set /a "freesize=%mc%/1000"
- echo %disk1%盘剩余空间为%freesize%MB
- echo 警戒值为%avail%MB
- if %freesize% LSS %avail% (goto xiaoyu) else (goto exit)
- :xiaoyu
- echo %disk1%盘空间不足%avail%MB,将电邮告警!
- echo 发电邮告警....(此功能由CmdMail实现,此处仅作演示说明。)
- ping -n 4 127.1>nul
- pause&&exit
-
- :exit
- echo 空间充裕,程序退出。&& echo %date% %time%:执行本程序,%disk1%盘磁盘空间%freesize%MB,未达到警戒值%avail%MB;>>%log_file_name%
- ping -n 4 127.1>nul
- exit
复制代码
作者: hnfeng 时间: 2018-10-30 14:51
会不会是超过了CMD可处理的最大数字了
BTW:你的颜色搭配太刺眼了吧
作者: Batcher 时间: 2018-10-30 14:55
BAT能够直接计算的数值大小非常有限,不适合用来判断磁盘空间,推荐使用PowerShell
http://bbs.bathome.net/thread-26200-1-1.html
作者: hnfeng 时间: 2018-10-30 15:27
或者使用第三方工具来计算
例如 http://bbs.bathome.net/thread-15369-1-2.html
不懂 powershell ,老了,学不动了
作者: yhcfsr 时间: 2018-10-30 18:05
32位的无符号整形最大值是2^32-1也就是4G,超过这个数字就会溢出.
非要用BAT的话,就采用BAT+JS或BAT+VBS的方式处理
作者: zds612 时间: 2018-10-31 15:05
回复 2# hnfeng
呵呵,可能我视力不好,感觉这样才看得清楚
作者: zds612 时间: 2018-10-31 15:06
回复 3# Batcher
看了看powershell,感觉很厉害很好用,但是batch都搞得我一头雾水,还是想想别的办法
感谢帮忙!
作者: zds612 时间: 2018-10-31 15:07
回复 4# hnfeng
非常感谢,我去研究研究,希望不会太难
作者: zds612 时间: 2018-10-31 15:08
回复 5# yhcfsr
vbs是个好办法,但我只会用来弹提示框,上面有个朋友提供了一个工具,我去看看,谢谢你!
作者: zds612 时间: 2018-10-31 15:11
回复 4# hnfeng
原帖里的链接失效了,你有保存附件吗?求分享:zds612@163.com
作者: Batcher 时间: 2018-10-31 16:06
回复 7# zds612
试试这个能看懂吗:批处理实现大数字加减乘除
http://bbs.bathome.net/thread-3372-1-1.html
作者: hnfeng 时间: 2018-11-1 09:13
回复 10# zds612
前面说的那个较大,传不上来。给你个更小的吧- C:\temp>set abc=1000000000000000000000
-
- C:\temp>ClCalc.exe %abc%/1000/1000/1000/1000/1000/1000
- 1000000000000000000000/1000/1000/1000/1000/1000/1000 = 1000
-
- C:\temp>ClCalc.exe %abc%/1024/1024/1024/1024/1024/1024
- 1000000000000000000000/1024/1024/1024/1024/1024/1024 = 867.361737988404
复制代码
没验证。你自己先验证这个计算结果是否准确
作者: zds612 时间: 2018-11-1 09:25
本帖最后由 zds612 于 2018-11-1 09:26 编辑
回复 11# Batcher
感谢大大的帮忙,对我很有帮助,已经可以正常计算了
但是出现另一个问题,不管警戒值设为多大,结果都是空间充裕
问题1:感觉好像我那个比较的if语句没有什么作用,能劳烦帮我看看嘛?
问题2:批处理中带小数的数字如何取整?- @echo off
- mode con cols=50 lines=10
- color 0a
- Title -[磁盘检测程序(自动电邮告警)]
- set log_file_name=RunLog.txt
- set lineno_max=365
- set avail=100000
- set svrname="测试服务器"
- set ipaddr="132.147.180.000"
- set freesize=0
- set num=1048576
- set disk1=c
-
- if NOT exist %log_file_name% (echo 执行日志:>%log_file_name%)
- for /f "delims=:" %%a in ('findstr/n .* "%log_file_name%"') do set lineno=%%a
- echo %log_file_name%文件共有%lineno%行
- if %lineno% GTR %lineno_max% (echo 执行日志:>%log_file_name% && echo %log_file_name%文件已经清空!)
-
- for /f "tokens=3 delims= " %%a in ('dir /-c %disk1%:') do set "mc=%%a"
- echo %mc%字节
-
-
- set suru=%mc%/%num%
- call :cu0 %suru:/= % freesize
-
- echo %disk1%盘剩余空间为%freesize%MB
- echo 警戒值为%avail%MB
- if %freesize% LSS %avail% (goto xiaoyu) else (goto exit)
- :xiaoyu
- echo %disk1%盘空间不足%avail%MB,将电邮告警!
- echo 发电邮告警....(此功能由CmdMail实现,此处仅作演示说明。)
- ping -n 4 127.1>nul
- pause&&exit
-
- :exit
- echo 空间充裕,程序退出。&& echo %date% %time%:执行本程序,%disk1%盘磁盘空间%freesize%MB,未达到警戒值%avail%MB;>>%log_file_name%
- ping -n 4 127.1>nul
- pause&&exit
-
-
- :cu0 500位内整数除法函数(封装)by @随风 bbs.bathome.net
- ::函数内有 cu1 cu2 cu3 cu4 四个标签,引用时需注意
- setlocal enabledelayedexpansion&set "lin=00000"
- set /a zongw=1000,cs1w=0,cs2w=0,falg=0,x=0
- if "!str!"=="1" Endlocal&set %~3=%ff%!num!&goto :EOF
- if "%~1"=="0" set sang=0&goto cu4
- if "!str!"=="0" set sang=以零为除数的错误。&goto cu4
- if not defined xiaosu set /a xiaosu=10
- for /l %%a in (1 1 5) do set "lin=!lin!!lin!!lin!"
- set sang=&set ppp=&set var1=%~1&set "var2=%~2"
- for /f "tokens=* delims=0" %%a in ("!var1!")do set var1=%%a
- for /f "tokens=* delims=0" %%a in ("!var2!")do set var2=%%a
- for /l %%a in (0 1 9)do (set "var1=!var1:%%a= %%a !"
- set "var2=!var2:%%a= %%a !")
- for %%a in (!var1!) do set /a cs1w+=1
- for %%a in (!var2!) do set /a cs2w+=1
- for /l %%a in (1 1 10) do (set t=&set cs=%~2&set/a j=0
- for /l %%b in (1 1 !cs2w!) do (set /a a=%%a*!cs:~-1!+j
- set t=!a:~-1!!t!&set a=0!a!&set "j=!a:~-2,1!"
- set cs=!cs:~0,-1!&set cs%%a=&set "bj%%a=")
- if !j! neq 0 (set cs%%a=!lin!!j!!t!&set "bj%%a=!j!!t!"
- ) else set cs%%a=!lin!!t!&set "bj%%a=!t!"
- set "cs%%a=!cs%%a:~-%zongw%!")
- set var2=!lin!!var2: =!&set "var2=!var2:~-%zongw%!"
- set /a cswc=cs1w-cs2w&set "var1=!var1: =!"
- if !cswc! lss 0 (set cswc=!cswc:-=!&set/a flag=1
- for /l %%a in (1 1 !cswc!)do (
- if %%a leq 11 set sang=0!sang!&set /a x=cswc-1
- set "var1=!var1!0")
- set "sang=!sang:~0,1!.!sang:~1!")
- set ppp=!var1:~0,%cs2w%!&set "var1=!var1:~%cs2w%!"
- if !flag! equ 1 (set /a bul=1) else set /a bul=0
- goto cu2
- :cu1
- if not defined var1 (set "var1=0"
- if not defined ppp goto cu4
- if !flag! equ 0 (set sang=!sang!.&set /a flag=1))
- set/a bul=1&set ppp=!ppp!!var1:~0,1!&set "var1=!var1:~1!"
- :cu2
- if !x! geq %xiaosu% goto cu4
- set pvar1=!lin!!ppp!&set "pvar1=!pvar1:~-%zongw%!"
- if "!pvar1!" lss "!var2!" (
- if !bul! equ 1 (set sang=!sang!0&set /a bul=0
- if !flag! equ 1 set /a x+=1)
- if "!ppp:~0,1!"=="0" set "ppp="
- goto cu1)
- if !flag! equ 1 set /a x+=1
- set /a bul=0
- ::计算商
- for /l %%a in (1 1 10) do (
- if "!cs%%a!" equ "!pvar1!" (
- set "sang=!sang!%%a"&set "yu=!bj%%a!"&goto cu3)
- if "!cs%%a!" gtr "!pvar1!" (set /a s=%%a-1
- set "sang=!sang!!s!"&set yu=!t!&goto cu3)
- set "t=!bj%%a!")
- :cu3 计算差
- set cjs=!ppp!&set cj1=&set m=&set/a jjj=0
- for /l %%a in (0 1 9) do set "cjs=!cjs:%%a= %%a !"
- for %%a in (!cjs!) do set "cj1=%%a !cj1!"
- for %%a in (!cj1!) do (if "!yu!"=="" set/a yu=0
- set /a a=%%a-jjj,b=!yu:~-1!
- if !a! lss !b! (set /a a+=10,jjj=1)else set/a jjj=0
- set /a w=a-b&set m=!w!!m!&set yu=!yu:~0,-1!)
- for /f "tokens=* delims=0" %%m in ("!m!") do (
- if "%%m"=="" (set m=0) else set "m=%%m")
- if !m! equ 0 (
- if "!var1:0=!"=="" set sang=!sang!!var1!&goto cu4
- set ppp=&goto cu1) else set "ppp=!m!"
- goto cu2
- :cu4
- if "!sang:~0,1!"=="." set "sang=0!sang!"
- Endlocal&set %~3=%ff%%sang%&goto :EOF
复制代码
作者: zds612 时间: 2018-11-1 09:32
回复 12# hnfeng
非常感谢,可以格式化输出吗?
只输出结果,不要等式?帮助信息里面好像没有提到参数(英文烂。。。)
谢谢你!
作者: hnfeng 时间: 2018-11-1 09:40
回复 6# zds612
我喜欢 color 3e
作者: Batcher 时间: 2018-11-1 10:06
http://bcn.bathome.net/s/tool/index.html?key=计算
这里有好几个命令行工具,可以试试。
作者: zds612 时间: 2018-11-1 13:25
回复 16# Batcher
是的,我也在里面找了几个,其中一个expr.exe可以实现需求- D:\bat_test>expr.exe 50 / 25
- 2
复制代码
但是我不会如何将计算结果赋值给变量,能否指导一下?谢谢!
作者: Batcher 时间: 2018-11-1 14:04
回复 17# zds612
放在 for /f 命令里面就行了,类似顶楼代码第15行。
作者: WHY 时间: 2018-11-1 21:30
本帖最后由 WHY 于 2018-11-3 16:02 编辑
个人认为,楼主无非是想判断磁盘剩余空间是否超过警戒值,没有必要转换成MB,补零就行了。
假设警戒值为 1GB- @echo off
- set "alarmValue=1073741824"
- for /f "tokens=3" %%i in ('dir /a /-c C:') do set "freeSpace=%%i"
- set "s1=00000000000000000000%freeSpace%"
- set "s2=00000000000000000000%alarmValue%"
- if "%s1:~-20%" LSS "%s2:~-20%" (
- echo;低于警戒值,发邮件
- ) else (
- echo;空间充足,剩余%freeSpace%字节,警戒值%alarmValue%字节
- )
- pause
复制代码
作者: WHY 时间: 2018-11-1 21:34
本帖最后由 WHY 于 2018-11-3 16:03 编辑
一定要转换为MB,这样应该可以:- @echo off & setlocal enabledelayedexpansion
- set "alarmValue=1024"
- for /f "tokens=3" %%i in ('dir /a /-c C:') do set "freeSpace=%%i"
- call :GetMB
- if !rt! LSS !alarmValue! (
- echo;低于警戒值,发邮件
- ) else (
- echo;空间充足,剩余!rt!MB,警戒值!alarmValue!MB
- )
- pause & exit /b
-
- :GetMB
- set "str=!freeSpace!FEDCBA9876543210" & set /a Len=0x!str:~16,1!
- for /L %%i in (0 1 !Len!) do (
- set "sang=!yu!!freeSpace:~%%i,1!"
- set /a yu=sang%%1048576,sang/=1048576
- if "!yu!" == "0" set "yu="
- set "rt=!rt!!sang!"
- )
- for /f "tokens=* delims=0" %%i in ("!rt!") do set /a rt=%%i+0
复制代码
欢迎光临 批处理之家 (http://www.bathome.net/) |
Powered by Discuz! 7.2 |