do-while循环仅在条件使用“和”而不是“或”时有效

时间:2014-02-27 04:13:27

标签: java do-while boolean-expression

我有一个使用以下条件的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");
    }
}

3 个答案:

答案 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”相同。如果你的逻辑变得更复杂,那么表可能会变大,但这种谨慎的推导可以防止最常见的错误。