【问题标题】:What is this method doing? (Arrays and random numbers)这个方法在做什么? (数组和随机数)
【发布时间】:2017-11-16 12:06:38
【问题描述】:

我的教科书给了我这段代码来帮助计算某个数字在整数数组中出现的次数。我试图将教科书给我的代码应用到我的作业中,但它似乎不起作用。基本上,我必须在一个数组中生成 30 个随机整数,上限为 15,下键为 -5。

我想知道数组中的一个数字等于 0、1、2... 直到 10 的次数。第一个代码是我的教科书给我的代码。他们还使用了随机数生成器,但他们不想找到等于 0、1 等的元素数量,而是想知道每个数字出现了多少次。 (分数数组只是随机数生成器,其上限为 100)。第二个代码是我的。

int[] counts = new int [100];
for (int i = 0; i < scores.length; i++) { 
int index = scores[i]; 
counts[index]++;
}


 //This is my code
 public static void main(String[] args) {
    int []a = arrayHist ();
    printArray (a);
}

public static int randomInt (int low, int high) {
    int range = (high - low) +1;
    return (int) (Math.random() * range) + low;

}

public static int[] randomIntArray (int x) {
    int[] random = new int[x];
    for (int i = 0; i< x; i++) {
        random [i] = randomInt (-5, 15);

    }
    return random;
}

public static int[] arrayHist () {
    int[] counts = new int [30];
    int[] hist = randomIntArray (30);
    for (int i = 0; i < 10 && i >= 0; i++) {
        int index = hist[i];
        counts[index]++;
    }
    return hist;
}


public static void printArray (int[] a) {
    for (int i = 0; i < a.length; i++) {
        System.out.println (a[i]);
    }
}

我应该只得到 11 个元素,但我又得到了 30 个随机数。这是为什么呢?

【问题讨论】:

  • 所以你的数组包含-5到15之间的30个随机数,但你只想计算值在0到10之间的次数? -5 到 -1 和 11 到 15 不算?
  • 仔细查看for (int i = 0; i &lt; 10 &amp;&amp; i &gt;= 0; i++) 以及您认为它在做什么与它实际上在做什么。另外,看看你返回了什么。
  • @CaiusJard 是的,没错
  • 我已经发布了一些有用的东西,但没有给你正确的答案来粘贴 - 如果你有兴趣了解正在发生的事情并解决它。如果您愿意,也许可以避免查看 Reiner Wei 的答案(除非您只是在粘贴答案之后),直到您“耐心自己解决这个问题”为止:) - 他直接写了答案,所以你现在可以选择你的方法。随时在任一答案的 cmets 中提出任何后续问题

标签: java arrays random


【解决方案1】:

我会在你的代码中加入一些 cmets,看看你能不能发现哪里出了问题:

//take a histogram of the array. We're only going to count values between 0 and 10
//so 25th to 75 centiles, ignoring values that are lower than 0 or higher than 10
public static int[] arrayHist () {

  //need to make an array of 11 numbers for the counts
  int[] counts = new int [30];

  //get an array of 30 random numbers
  int[] hist = randomIntArray (30);

  //loop over the whole array of 30 numbers
  for (int i = 0; i < 10 && i >= 0; i++) {
    //retrieve the random number into a variable temporarily
    int index = hist[i];

    //if the value is too low or too high, skip it

    //else, store it in the counts array - the value from the random array
    //serves as the index position in the counts array        
    counts[index]++;
  }

  //return the counts array
  return hist;
}

我对我的 cmets 所做的相当于使用您认为的语言(英语)设计算法,然后您可以将其翻译成您正在学习的语言(java)。很少有开发人员以他们编写的编程语言进行思考。作为一名学生,我建议您始终编写 cmets 来向自己解释您的算法,然后再在 cmets 下编写代码。编写 cmets(通常)会获得积分,因此如果您先编写它们,那么 a)它可以帮助您编写代码 b)在代码工作后您无需编写 cmets 的繁琐工作

为了您自己的利益/学习,请在查看下面的剧透(答案)之前尝试从上面找出问题所在。将鼠标悬停在框上即可显示剧透

 //loop over the whole array of 30 numbers - YOU ONLY LOOP 10
 for (int i = 0; i < 10 && i >= 0; i++) {
   //if the value is too low or too high, skip it - YOU DIDN'T DO THIS CHECK
   ...
 }
 //return the counts array - YOU RETURNED THE WRONG ARRAY
 return hist;

针对 cme​​ts 的编辑:

检查范围

您必须检查两个限制,因此它需要是以下形式之一:

if(x < 0 || x > 10) then don't do the count

if(!(x >= 0 && x <= 10)) then don't do the count

if(x >= 0 && x <= 10) then do the count

if(!(x < 0 || x > 10)) then do the count

使用 NOT(感叹号 !)的测试通常更难阅读和理解,因此尽量避免使用它们是可能的。 “积极思考”的测试 - 即它们返回正面结果而不是需要否定的负面结果 - 更容易阅读和理解。

在错误检查方面,循环和方法的一个有用提示是测试满足特定条件的错误值,如果遇到错误值,则跳过处理循环的其余部分(使用 continue ) 关键字,或跳过该方法的其余部分(通过 returning 从它)

这样做意味着您的 if 主体({ 和 } 之间的位)不会变得庞大。比较:

for(...){
  if(test for bad values)
    continue;

  //50 lines long loop body
}

比做更整洁:

for(...){
  if(test for goodvalues){
    //50 lines long loop body
  }
}

如果你使用底部模式,你可能会在几个 IF 之后出现真正的缩进混乱,到处都是 { 和 },你的代码就在屏幕的右侧:

    for(...){
        //code
        if(...){
            //code
            if(...){
                //code
                if(...){
                    //code
                    if(...){
                        //code
                        if(...){
                            //code
                            if(...){
                                //code
                            }
                            //code
                        }
                        //code
                    }
                    //code
                }
                //code
            }
            //code
        }
        //code
    }

将缩进级别保持在最低水平有助于使您的代码更具可读性

因此,在您的情况下,我建议您不要测试在 0 到 10 范围内的值并对其进行处理,而是采用“如果值在 0 到 10 范围内”的形式,跳过执行循环的其余部分

【讨论】:

  • 为了确保数字在0到10之间,我应该写一个if-else语句吗?
  • 您确实应该,我将编辑答案的正文以提供扩展说明
  • @CaiusJard:很高兴您鼓励 OP 为他/她自己学习 - 这么多人只想抓着就跑。在 2 天内提醒我获得 +50 奖励!
  • 我应该把计时的工作交给我组织得更好的另一半 :)
【解决方案2】:

您的 arrayHist() 方法只返回带有随机数的数组。应该更像这样:

public static int[] arrayHist() {
    // generate array with random numbers
    int[] hist = randomIntArray(30);
    // initialize the array for counting
    int[] counts = new int[11];
    // step through the random numbers array and increase corresponding counter if the number's values is between 0 and 10
    for (int j = 0; j < hist.length; j++) {
        int number = hist[j];
        if (number > -1 && number < 11) {
            counts[number]++;
        }
    }
    return counts;
}

【讨论】:

  • new int[10]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} 更具可读性。
  • 很好,但是从问题的标题来看,这显然是大学工作,我想说“解释”部分比“正确答案”部分更重要。
猜你喜欢
  • 1970-01-01
  • 2015-04-23
  • 1970-01-01
  • 1970-01-01
  • 2021-08-26
  • 1970-01-01
  • 2021-10-04
  • 2012-01-20
  • 1970-01-01
相关资源
最近更新 更多