[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[数值计算] [讨论]批处理if命令数值比较何时发生溢出错误

WinXP 环境下, cmd 所能处理的数值范围是 [-2^31,  2^31-1], 之前认为 运算结果 超出此范围才发生溢出错误, 而在此范围内的 数值比较 不会发生溢出错误, 但是其实不然.  当两个数都在这个范围内, 但它们的差值的绝对值 大于或等于 2^31-1, 仍将发生溢出错误. 详见下面代码及运行结果:
  1. @echo off
  2. (for /l %%i in (-2147483648,1,-2147483638) do (
  3.   for  /l %%j in (-10,1,10) do (
  4.     if %%j gtr %%i (echo %%j>%%i)   else (echo %%j<=%%i)
  5.     if %%j geq %%i (echo %%j>=%%i) else (echo %%j<=%%i)
  6.     if %%j equ %%i (echo %%j==%%i) else (echo %%j≠%%i)
  7.     if %%j leq %%i (echo %%j<=%%i) else (echo %%j>%%i)
  8.     if %%j lss %%i (echo %%j<%%i)   else (echo %%j>=%%i)
  9. )))>t.txt
  10. type t.txt | findstr "<"&&pause
  11. :bigPlus
  12. echo 以下是大数接近 2^^31-1 的情况
  13. for  /l %%j in (2147483637,1,2147483647) do (
  14.   for /l %%i in (-10,1,10) do (
  15.     if %%j gtr %%i (echo %%j>%%i)   else (echo %%j<=%%i)
  16.     if %%j geq %%i (echo %%j>=%%i) else (echo %%j<=%%i)
  17.     if %%j equ %%i (echo %%j==%%i) else (echo %%j≠%%i)
  18.     if %%j leq %%i (echo %%j<=%%i) else (echo %%j>%%i)
  19.     if %%j lss %%i (echo %%j<%%i)   else (echo %%j>=%%i)
  20.   )>t.txt
  21.   type t.txt | findstr "<"&&pause
  22. )
复制代码
在小的数接近 -2^31 时, 比较结果会发生溢出错误(差值溢出), 但显示的数值正常.
而在大数接近 2^31-1 时, 发生溢出错误时, 连显示的数值也出现错误 -- 标号 :bigPlus 后面的代码中, %%j 的取值一直是正数, 但显示结果却成了负数).
部分错误结果如下, 要查看完全的结果请运行上面的测试代码 及 扩大测试的范围

0<=-2147483648
0<=-2147483648
0<=-2147483648
0<-2147483648
1<=-2147483648
1<=-2147483648
1<=-2147483648
1<-2147483648
2<=-2147483648
2<=-2147483648
2<=-2147483648
2<-2147483648
.
.
.
1<=-2147483647
...
2<=-2147483646
...
3<=-2147483645
...
10<=-2147483638
10<=-2147483638
10<=-2147483638
10<-2147483638
请按任意键继续. . .
以下是大数接近 2^31-1 的情况
-2147483638<=10
-2147483638<=10
-2147483638<=10
-2147483638<10
请按任意键继续. . .
-2147483637<=10
-2147483637<=10
-2147483637<=10
-2147483637<10
请按任意键继续. . .

[ 本帖最后由 neorobin 于 2010-4-17 18:13 编辑 ]

回复 2楼 的帖子

在高级程序语言中, 两个数值本身没有溢出, 比较时是不会产生溢出错误的, 例如, 在 PASCAL 中
  1. begin
  2.   if 2147483647 > -2147483647 then Write('2147483647>-2147483647') else Write('2147483647<=-2147483647');
  3.   Readln;
  4. end.
复制代码
可正常输出结果:
2147483647>-2147483647

但试图
  1. if 2147483647 > -2147483648 then Write('...');
复制代码
却将引起编译报错

关于循环界限, 确实如你所言, 上限改成 2147483646 后, 循环就可以正常终止, 而且也不产生错误的比较结果

[ 本帖最后由 neorobin 于 2010-4-17 23:27 编辑 ]

TOP

返回列表