首页    新闻    下载    文档    论坛     最新漏洞    黑客教程    数据库    搜索    小榕软件实验室怀旧版    星际争霸WEB版    最新IP准确查询   
名称: 密码:      忘记密码  马上注册
操作系统 :: windows

JAVA 解惑文章(谜题26:在循环中)


http://www.gipsky.com/
<p align="left" style="margin: 0cm 0cm 0pt; text-align: left;" class="MsoNormal"><span style="font-size: 12pt; font-family: 宋体;">下面的程序计算了一个循环的迭代次数,并且在该循环终止时将这个计数值打印了出来。那么,它打印的是什么呢? <span lang="EN-US" style="color: rgb(51, 51, 204);"><o:p></o:p></span></span></p>

<p align="left" style="margin: 0cm 0cm 0pt; text-align: left;" class="MsoNormal"><span lang="EN-US" style="font-size: 12pt; color: rgb(51, 51, 204); font-family: 宋体;">public class InTheLoop {<o:p></o:p></span></p>

<p align="left" style="margin: 0cm 0cm 0pt; text-align: left;" class="MsoNormal"><span lang="EN-US" style="font-size: 12pt; color: rgb(51, 51, 204); font-family: 宋体;"><span style=""> </span>public static final int END = Integer.MAX_VALUE;<o:p></o:p></span></p>

<p align="left" style="margin: 0cm 0cm 0pt; text-align: left;" class="MsoNormal"><span lang="EN-US" style="font-size: 12pt; color: rgb(51, 51, 204); font-family: 宋体;"><span style=""> </span>public static final int START = END - 100;<o:p></o:p></span></p>

<p align="left" style="margin: 0cm 0cm 0pt; text-align: left;" class="MsoNormal"><span lang="EN-US" style="font-size: 12pt; color: rgb(51, 51, 204); font-family: 宋体;"><span style=""> </span>public static void main(String[] args) {<o:p></o:p></span></p>

<p align="left" style="margin: 0cm 0cm 0pt; text-align: left;" class="MsoNormal"><span lang="EN-US" style="font-size: 12pt; color: rgb(51, 51, 204); font-family: 宋体;"><span style=""> </span>int count = 0;<o:p></o:p></span></p>

<p align="left" style="margin: 0cm 0cm 0pt; text-align: left;" class="MsoNormal"><span lang="EN-US" style="font-size: 12pt; color: rgb(51, 51, 204); font-family: 宋体;"><span style=""> </span>for (int i = START; i <= END; i )<o:p></o:p></span></p>

<p align="left" style="margin: 0cm 0cm 0pt; text-align: left;" class="MsoNormal"><span lang="EN-US" style="font-size: 12pt; color: rgb(51, 51, 204); font-family: 宋体;"><span style=""> </span>count ;<o:p></o:p></span></p>

<p align="left" style="margin: 0cm 0cm 0pt; text-align: left;" class="MsoNormal"><span lang="EN-US" style="font-size: 12pt; color: rgb(51, 51, 204); font-family: 宋体;"><span style=""> </span><span style=""> </span>System.out.println(count);<o:p></o:p></span></p>

<p align="left" style="margin: 0cm 0cm 0pt; text-align: left;" class="MsoNormal"><span lang="EN-US" style="font-size: 12pt; color: rgb(51, 51, 204); font-family: 宋体;"><span style=""> </span>}<o:p></o:p></span></p>

<p align="left" style="margin: 0cm 0cm 0pt; text-align: left;" class="MsoNormal"><span lang="EN-US" style="font-size: 12pt; color: rgb(51, 51, 204); font-family: 宋体;">}<o:p></o:p></span></p>

<p align="left" style="margin: 0cm 0cm 0pt; text-align: left;" class="MsoNormal"><span style="font-size: 12pt; font-family: 宋体;">如果你没有非常仔细地查看这个程序,你可能会认为它将打印<span lang="EN-US">100</span>,因为<span lang="EN-US">END</span>比<span lang="EN-US">START</span>大<span lang="EN-US">100</span>。如果你稍微仔细一点,你可能会发现该程序没有使用典型的循环惯用法。大多数的循环会在循环索引小于终止值时持续运行,而这个循环则是在循环索引小于或等于终止值时持续运行。所以它会打印<span lang="EN-US">101</span>,对吗?<span lang="EN-US"> <o:p></o:p></span></span></p>

<p align="left" style="margin: 0cm 0cm 0pt; text-align: left;" class="MsoNormal"><span style="font-size: 12pt; font-family: 宋体;">嗯,根本不对。如果你运行该程序,就会发现它压根就什么都没有打印。更糟的是,它会持续运行直到你撤销它为止。它从来都没有机会去打印<span lang="EN-US">count</span>,因为在打印它的语句之前插入的是一个无限循环。<span lang="EN-US"> <o:p></o:p></span></span></p>

<p align="left" style="margin: 0cm 0cm 0pt; text-align: left;" class="MsoNormal"><span style="font-size: 12pt; font-family: 宋体;">问题在于这个循环会在循环索引(<span lang="EN-US">i</span>)小于或等于<span lang="EN-US">Integer.MAX_VALUE</span>时持续运行,但是所有的<span lang="EN-US">int</span>变量都是小于或等于<span lang="EN-US">Integer.MAX_VALUE</span>的。因为它被定义为所有<span lang="EN-US">int</span>数值中的最大值。当<span lang="EN-US">i</span>达到<span lang="EN-US">Integer.MAX_VALUE</span>,并且再次被执行增量操作时,它就有绕回到了<span lang="EN-US">Integer.MIN_VALUE</span>。<span lang="EN-US"> <o:p></o:p></span></span></p>

<p align="left" style="margin: 0cm 0cm 0pt; text-align: left;" class="MsoNormal"><span style="font-size: 12pt; font-family: 宋体;">如果你需要的循环会迭代到<span lang="EN-US">int</span>数值的边界附近时,你最好是使用一个<span lang="EN-US">long</span>变量作为循环索引。只需将循环索引的类型从<span lang="EN-US">int</span>改变为<span lang="EN-US">long</span>就可以解决该问题,从而使程序打印出我们所期望的<span lang="EN-US">101</span>:<span lang="EN-US"> <o:p></o:p></span></span></p>

<p align="left" style="margin: 0cm 0cm 0pt; text-align: left;" class="MsoNormal"><span lang="EN-US" style="font-size: 12pt; color: rgb(51, 51, 204); font-family: 宋体;">for (long i = START; i <= END; i )<o:p></o:p></span></p>

<p align="left" style="margin: 0cm 0cm 0pt; text-align: left;" class="MsoNormal"><span style="font-size: 12pt; font-family: 宋体;">更一般地讲,这里的教训就是<span lang="EN-US">int</span>不能表示所有的整数。无论你在何时使用了一个整数类型,都要意识到其边界条件。如果其数值下溢或是上溢了,会怎么样呢?所以通常最好是使用一个取之范围更大的类型。(整数类型包括<span lang="EN-US">byte</span>、<span lang="EN-US">char</span>、<span lang="EN-US">short</span>、<span lang="EN-US">int</span>和<span lang="EN-US">long</span>。)<span lang="EN-US"> <o:p></o:p></span></span></p>

<p align="left" style="margin: 0cm 0cm 0pt; text-align: left;" class="MsoNormal"><span style="font-size: 12pt; font-family: 宋体;">不使用<span lang="EN-US">long</span>类型的循环索引变量也可以解决该问题,但是它看起来并不那么漂亮: <span lang="EN-US" style="color: rgb(51, 51, 204);"><o:p></o:p></span></span></p>

<p align="left" style="margin: 0cm 0cm 0pt; text-align: left;" class="MsoNormal"><span lang="EN-US" style="font-size: 12pt; color: rgb(51, 51, 204); font-family: 宋体;">int i = START;<o:p></o:p></span></p>

<p align="left" style="margin: 0cm 0cm 0pt; text-align: left;" class="MsoNormal"><span lang="EN-US" style="font-size: 12pt; color: rgb(51, 51, 204); font-family: 宋体;">do {<o:p></o:p></span></p>

<p align="left" style="margin: 0cm 0cm 0pt; text-align: left;" class="MsoNormal"><span lang="EN-US" style="font-size: 12pt; color: rgb(51, 51, 204); font-family: 宋体;"><span style=""> </span>count ;<o:p></o:p></span></p>

<p align="left" style="margin: 0cm 0cm 0pt; text-align: left;" class="MsoNormal"><span lang="EN-US" style="font-size: 12pt; color: rgb(51, 51, 204); font-family: 宋体;">}while (i != END);<o:p></o:p></span></p>

<p align="left" style="margin: 0cm 0cm 0pt; text-align: left;" class="MsoNormal"><span style="font-size: 12pt; font-family: 宋体;">如果清晰性和简洁性占据了极其重要的地位,那么在这种情况下使用一个<span lang="EN-US">long</span>类型的循环索引几乎总是最佳方案。<span lang="EN-US"> <o:p></o:p></span></span></p>

<p align="left" style="margin: 0cm 0cm 0pt; text-align: left;" class="MsoNormal"><span style="font-size: 12pt; font-family: 宋体;">但是有一个例外:如果你在所有的(或者几乎所有的)<span lang="EN-US">int</span>数值上迭代,那么使用<span lang="EN-US">int</span>类型的循环索引的速度大约可以提高一倍。下面是将<span lang="EN-US">f</span>函数作用于所有<span lang="EN-US">40</span>亿个<span lang="EN-US">int</span>数值上的惯用法: <span lang="EN-US" style="color: rgb(51, 51, 204);"><o:p></o:p></span></span></p>

<p align="left" style="margin: 0cm 0cm 0pt; text-align: left;" class="MsoNormal"><span lang="EN-US" style="font-size: 12pt; color: rgb(51, 51, 204); font-family: 宋体;">//Apply the function f to all four billion int values<o:p></o:p></span></p>

<p align="left" style="margin: 0cm 0cm 0pt; text-align: left;" class="MsoNormal"><span lang="EN-US" style="font-size: 12pt; color: rgb(51, 51, 204); font-family: 宋体;">int i = Integer.MIN_VALUE;<o:p></o:p></span></p>

<p align="left" style="margin: 0cm 0cm 0pt; text-align: left;" class="MsoNormal"><span lang="EN-US" style="font-size: 12pt; color: rgb(51, 51, 204); font-family: 宋体;">do {<o:p></o:p></span></p>

<p align="left" style="margin: 0cm 0cm 0pt; text-align: left;" class="MsoNormal"><span lang="EN-US" style="font-size: 12pt; color: rgb(51, 51, 204); font-family: 宋体;"><span style=""> </span>f(i);<o:p></o:p></span></p>

<p align="left" style="margin: 0cm 0cm 0pt; text-align: left;" class="MsoNormal"><span lang="EN-US" style="font-size: 12pt; color: rgb(51, 51, 204); font-family: 宋体;">}while (i != Integer.MAX_VALUE);<o:p></o:p></span></p>

<span style="font-size: 12pt; font-family: 宋体;">该谜题对语言设计者的教训与谜题<span lang="EN-US">3</span>相同:可能真的值得去考虑,应该对那些不会在产生溢出时而不抛出异常的算术运算提供支持。同时,可能还值得去考虑,应该对那些在整数值范围之上进行迭代的循环进行特殊设计,就像许多其他语言所做的那样。</span>







<h6>您可能感兴趣的:</h6>
<p><a target="_blank" href="" title="更多相关内容">更多相关内容</a></p>
<ul>
</ul>
<< JAVA 解惑文章(谜题27:变幻莫测的i值) DataGuard-ORA-00261错误 >>
API:
gipsky.com& 安信网络
网友个人意见,不代表本站立场。对于发言内容,由发表者自负责任。

系统导航

 

Copyright © 2001-2010 安信网络. All Rights Reserved
京ICP备05056747号