标题:
[数值计算]
修改并解析批处理平闰年判断公式
[打印本页]
作者:
batman
时间:
2011-9-17 02:41
标题:
修改并解析批处理平闰年判断公式
大家在平常的批处理计算中用到如下公式来判断平闰年:
set /a "yp=!(year%%4)&!(!(year%%100))|!(year%%400)"
在上式中当yp的值为1时即表示year为闰年,当yp的值为0是即表示year为平年。也许有人会问了,当yp为其他值呢(不为1也不为0)?其实上式中的yp只有可能是1或0,为什么,下面我就来解释解释:
首先我们来认识一下“!”,请注意在这里它不是我们平常开启变量延迟时所用的变量符号“!”,它在运算式中充当的角色是一元运算符,因此在开启变量延迟的情况下请注意使用^将其转义。那么这个一元运算符“!”究竟是起得什么作用呢?它所起的作用就是将任意结果值变为0和1,当其运算的对象值不为0时,其运算结果为0,只有当其运算的对象值为0时,其运算结果才为1。如果你不是很明白就请在cmd中set /a "a=!b",然后任意更换b的值看a值的变化吧。
其次,我们再来认识一下%%运算符,没错它就是我们经常用到的取余运算符,set /a a=b%%c,取b/c的余数,其实在cmd中写法是set /a a=b%c与批处理还是有所区别的。关于取余运算在论坛有大量的帖子进行了描述,在这里我就不再赘述了。只是我们将这个取余和一元运算符结合起来,如set /a "a=!(b%%c)",当b能整除c时a值为1反之则为0,这一点我相信大家都能明白。
接下来,我们再认识三个位运算符号“&”“^”“|”,它们分别是按位与、按位异、按位或、为了方便理解,请大家忽视掉“按位”这两个关键字,这是在二进制的位概念。而在这里我们面对只是1和0的位运算(因为一元运算符运算后只会产生1和0的结果,以下的运算式中我们也只考虑这一特殊情况),所以不存在按位的问题。set /a "a=b&c"只有bc都为1时a才为1否则为0,set /a "a=b^c"只有bc为一0一1时a才为1否则为0,set /a "a=b|c"当bc中任一个为1时a为1否则为0。
对了在这里我还要解释一个概念,什么是闰年?所谓闰年是指同时能整除100和400以及不能整除100却能整除4的年份,那么,所有的年份整除4、100、400就只有四种情况,第一种情况能整除400的就能整除100和4(闰年);第二种情况不能整除400但能整除100和4(平年);第三种情况不能整除400和100但能整除4(闰年);第四种情况不能整除400、100和4(平年)。分别举例如:2000是闰年,1900年是平年,2048年是闰年,1721年是平年。
好了,现在我们来分析最上面的公式set /a "yp=!(year%%4)&!(!(year%%100))|!(year%%400)",当年份year值为第一种情况时year%%4 year%%100 year%%400的值都是0,一元运算后值都是1,大家注意到!(!(year%%100))这里实际做了两次一元运算,也就是说公式可以简化成 set /a "yp=1&0|1",运过上面学到的位运算知识,我们不难得出yp=1;当year值为第二种情况时,year%%4的值为0,一元运算后为1,year%%100的值为0,两次一元运算后值为0,year%%400的值不为0,一元运算后值为0,公式简化为set /a "yp=1&0|0",yp=0,后面两种情况相信大家都能同样推算出来了。所以上面公式的值只有可能是1或0。
可以说这个公式真的很经典很牛b,在相当长的一段时间内我都是严格按照原作者的思路来背写公式并运用到各种批处理闰年判断运算中去的。但是,今天再一次看到这个公式时突然想到了按位异运算符“^”的作用,并再次分析了公式的运算情况,终于改写了这一公式如下,虽然变化不是很大,但总算精简了原公式并更便于大家理解:
set /a "yp=!(year%%4)^!(year%%100)|!(year%%400)"(大家仔细观察相对于原公式的变化)
为什么能这样改写?原因如下:
实际上我们就是要在公式中实现1运算1运算1=1,1运算1运算0=0,1运算0运算0=1,0运算0运算0=0这四种情况(1代表整除后一元运算0代表不能整除后一元运算),原公式1&!1|1=1,1&!1|0=0,1&!0|0=1,0&!0|0=0,而改写公式后1^1|1=1,1^1|0=0,1^0|0=1,0^0|0=0,完全可以满足所有条件。
作者:
hfg1977
时间:
2011-9-17 08:08
只能说学习了, 一直对set中运算不求甚解,只用自己理解的方法.
作者:
Batcher
时间:
2011-9-17 09:20
我们再认识三个位运算符号“&”“^”“|”,它们分别是按位或、按位异、按位与
这个顺序需要调整一下吧
作者:
batman
时间:
2011-9-17 09:50
回复
3#
Batcher
感谢batcher及时指出,已更正。。。
作者:
lxzzr
时间:
2011-9-17 16:12
本帖最后由 lxzzr 于 2011-9-17 16:14 编辑
用PowerShell,如果是闰年则返回true:
[datetime]::isleapyear(2011)
复制代码
作者:
cjiabing
时间:
2011-10-18 00:00
回复 2# hfg1977
哈哈,我对SET也是只懂皮毛,这种非专业的真不懂。
欢迎光临 批处理之家 (http://bathome.net./)
Powered by Discuz! 7.2