我有一个使用以下条件的do-while循环:while(p!=0 && k!=0);
。当我使用&&
作为运算符时,循环工作正常。但是,出于程序的目的,我需要使用||
。循环运行一次然后挂起而不会抛出任何异常。谁能告诉我为什么do-while循环挂起?带注释的完整代码:
//Import necessary dependencies
import java.util.*;
import javax.swing.JFrame;
import org.math.plot.*;
public class fixedSimulation
{
//Initialize variables
public static int pacifists, killers, deaths, survivals, csvIndex = 0;
public static double[] csvProb = new double[121];
public static int[] csvParamP = new int[121], csvParamK = new int[121];
public static void main(String[] args)
{
//These "for" loops serve to run the simulation 100 times for every possible combination of 0-10 pacifists and 0-10 killers
for(int p = 0; p<11; p++)
{
pacifists = p;
for(int k = 0 ;k<11; k++)
{
killers = k;
//Display the number of pacifists and killers in current group (100 trials) of simulations
System.out.println("P" + p + "K" + k);
deaths = 0; survivals = 0;
for(int t=0; t<100; t++)
{
//Run simulation
doRun();
//Display current total of deaths and survivals for simulation group
System.out.println("\nDeaths=" + deaths + " Survivals=" + survivals);
//Display current probability for simulation group
System.out.println("Probability of survival = " + (((double)survivals/(double)(survivals+deaths))*100) + "%\n");
}
//Record data for later use
csvProb[csvIndex] = (((double)survivals/(double)(survivals+deaths))*100);
csvParamP[csvIndex] = p;
csvParamK[csvIndex] = k;
csvIndex++;
}
}
//Display collected data in "Comma-separated value" format, for easy use in spreadsheet applications
System.out.print("CSV Data:\nPacifists,Killers,Probability");
for(int x = 0; x < 121; x++)
{
System.out.print("\n" + csvParamP[x] + "," + csvParamK[x] + "," + csvProb[x]);
}
//Prepare to display scatter plot
System.out.println("\nPlotting");
//Create arrays for plot data
double[] plotX = new double[121], plotY = new double[121], plotZ = new double[121];
//Populate arrays
for(int x = 0; x < 121; x++)
{
plotX[x] = csvParamP[x];
plotY[x] = csvParamK[x];
plotZ[x] = csvProb[x];
}
//Initialize plotting panel
Plot3DPanel plotPanel = new Plot3DPanel();
plotPanel.addScatterPlot("Plot", plotX, plotY, plotZ);
plotPanel.setAxisLabels("Pacifists", "Killers", "Probability of Survival");
System.out.println("Plot Done, opening frame");
//Create UI window
JFrame plotFrame = new JFrame("Pacifists and Killers");
plotFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
plotFrame.setSize(700, 700);
plotFrame.setContentPane(plotPanel);
plotFrame.setVisible(true);
System.out.println("Frame opened");
}
//Simulation method
public static void doRun()
{
//Instantiate values for test
int p=pacifists, k=killers;
//"do" loop simulates meeting, checks to see if there are still killers and pacifists to meet, and if so simulates subsequent meetings
do
{
Random r = new Random();
//Pick two numbers between 0 and 2; random result of 0 is pacifist, 1 is killer. 2 is used as upper limit because random limit is exclusive.
int r1 = r.nextInt(2), r2 = r.nextInt(2);
//Check to see if 2 pacifists have met (if first number [r1] is 0 and second number [r2] is 0)
if( (r1==0 && r2==0) && (p>=2) /* Check to see if there are 2+ pacifists; must be 2+ pacifists for them to meet */ )
{
//Display meeting and result
System.out.println("P&P: P=" + p + " K=" + k);
}
//Check to see if a pacifist and killer have met (if first number [r1] is 0 and second number [r2] is 1)
else if( ((r1==0 && r2==1) || (r1==1 && r2==0)) && (p>=1 && k>=1) /* Check to see if there are 1+ pacifist(s) and 1+ killer(s); must be 1+ pacifist(s) and 1+ killer(s) for them to meet */)
{
//Remove pacifist
p--;
//Display meeting and result
System.out.println("P&K: P=" + p + " K=" + k);
}
//Check to see if 2 killers have met (if first number [r1] is 1 and second number [r2] is 1)
else if( (r1==1 && r2==1) && (k>=2) /* Check to see if there are 2+ killers; Must be 2+ killers for them to meet */ )
{
//Remove 2 killers
k-=2;
//Display meeting and result
System.out.println("K&K: P=" + p + " K=" + k);
}
}
//Check to see that pacifists and killers still exist
------> while(p!=0 || k!=0); <------
//Display and record final result
if(k==0)
{
System.out.println("Traveler survives");
survivals++;
}
else if(k!=0)
{
System.out.println("Traveler dies");
deaths++;
}
//Catch extraneous errors
else System.out.println("ERROR: Unknown end");
}
}
答案 0 :(得分:1)
通过@anonymous
更正先前的评论 p!=0 && k!=0 is equal to !(p == 0 || k == 0)
答案 1 :(得分:0)
在此代码中使用while(p!=0 || k!=0)
(如your comment中所述)存在一些问题。
当k
为{{1>}时(在doRun
的第一次调用中开始),您创建了一个无限循环,因为您需要{{1} }进入减少的块:
k >= 2
因此else if( (r1==1 && r2==1) && (k>=2) /* Check to see if there are 2+ killers; Must be 2+ killers for them to meet */ )
{
//Remove 2 killers
k-=2;
//Display meeting and result
System.out.println("K&K: P=" + p + " K=" + k);
}
永远不会减少,k
将永远为真。
有一些方法可以解决这个问题,从而揭示相关问题。如果p!=0 || k!=0
开始奇数,它永远不会为零。它会从k
跳到1
,但您正在使用-1
检查不平等,而不是使用0
。
在更基础的层面上,为什么要在>
和p
都为零之前运行循环?在您的方案中似乎做错了。
完全独立,不需要在循环内不断创建新的k
对象。创建一次然后重复调用Random
。
答案 2 :(得分:0)
所以,请注意几点。
正如其他人评论和回答的那样,DeMorgan的法律显示了将逻辑语句从使用AND转换为使用OR的正确方法。正如您所发现的那样,只需用OR替换AND就不会导致问题的结束。在将来,我建议使用调试器(可能在Eclipse中?)来逐步完成逻辑并确切了解它是如何解析的。
但更普遍的是,这样的逻辑陈述没有神奇之处。证明DeMorgan工作的最简单方法是设置逻辑表:
| Expression 1 || | Expression 2
p!=0 | k!=0 | (p!=0 && k!=0) || p==0 | k==0 | (p==0 || k==0) | !(p==0 || k==0)
------+------+----------------++------+------+----------------+-----------------
true | true | true ||false |false | false | true
true |false | false ||false | true | true | false
false | true | false || true |false | true | false
false |false | false || true | true | true | false
这些表格很容易绘制,我希望很容易理解。您可以看到左侧的“表达式1”与右侧的“表达式2”相同。如果你的逻辑变得更复杂,那么表可能会变大,但这种谨慎的推导可以防止最常见的错误。