How to nail down the java.lang.ArrayIndexOutOfBoundsException cause? - java

This is a continuation from:
Recursive Fibonacci memoization.
I keep getting
an java.lang.ArrayIndexOutOfBoundsException error when trying to run the code. I'm getting the error on lines 63 and 40 which are
63: int fib = dictionary[num]; // dictionary is a class level array.
40: answer = fibonacci(num); // Answer is an int calling the fibonacci function and passing "num" to it.
Here is the full code:
import javax.swing.JOptionPane;
public class question2
{
//class variable
static int count = 0;
static int [] dictionary;
//main method
public static void main(String[] args)
{
//user input
int num = Integer.parseInt(JOptionPane.showInputDialog("Enter num:")), answer;
//Catches negative numbers, exits
if (num < 0)
{
JOptionPane.showMessageDialog(null,"ERROR: fibonacci sequence not defined for negative numbers.");
System.exit(1);
}
//info dialog
JOptionPane.showMessageDialog(null,"About to calculate fibonacci("+num+")");
//giving the array "num" elements
dictionary = new int [num];
//fill array with 0
for (int i=0; i<dictionary.length;i++)
dictionary[i]=0;
//adds value of 1 for fib(1)
if (dictionary.length>=2)
dictionary[1]= 1;
//method call
answer = fibonacci(num);
//output
JOptionPane.showMessageDialog(null,"Fibonacci("+num+") is "+answer+" (took "+count+" calls)");
}
static int fibonacci(int num)
{
count++;
// Base cases: f(0) is 0, f(1) is 1
if (num==0)
return 0;
if (num==1)
return 1;
// Other cases: f(num) = f(num-1) + f(num-2)/
else
{
//check array for value
int fib = dictionary[num];
//add new value to array
if (fib==0)
{
fib = fibonacci(num-1) + fibonacci(num-2);
dictionary[num] = fib;
}
return fib;
}
}
} //class terminator

The array is of size num (int fib = dictionary[num];) so the max index you can access is num-1. You try to access index num (dictionary[num] = fib;) which is out of bounds.

Related

Finding the occurrence of values within an array

My question is how do I find the frequency of the numbers "8" and "88" in this array, using a method. It seems as what I put in the assessor method does not appear to work. For example, if "8" occurs three times in the array the output would be "3" and the same for "88".
If I am wrong please point me to the right direction. Any help with my question is greatly appreciate.
import java.util.Random;
public class ArrayPractice {
private int[] arr;
private final int MAX_ARRAY_SIZE = 300;
private final int MAX_VALUE = 100;
public ArrayPractice() {
// initialize array
arr = new int[MAX_ARRAY_SIZE];
// randomly fill array with numbers
Random rand = new Random(1234567890);
for (int i = 0; i < MAX_ARRAY_SIZE; ++i) {
arr[i] = rand.nextInt(MAX_VALUE) + 1;
}
}
public void printArray() {
for (int i = 0; i < MAX_ARRAY_SIZE; ++i)
System.out.println(arr[i]);
}
public int countFrequency(int value) {
for (int i: MAX_VALUE) {
if (i == 8)
i++;
}
public static void main(String[] args) {
ArrayPractice ap = new ArrayPractice();
System.out.println("The contents of my array are: ");
ap.printArray();
System.out.println("");
System.out.println("The frequency of 8 is: " + ap.countFrequency(8));
System.out.println("The frequency of 88 is: " + ap.countFrequency(88));
}
}
}
You need to iterate over arr and increment a variable when an element matches value.
public int countFrequency(int value) {
int count = 0;
for (int num : arr) {
if (num == value) {
count++;
}
}
return count;
}
You have a hard-coded seed, so your random values won't be random on different runs. You are also hard-coding your frequency count against 8 (instead of value). But honestly, I suggest you revisit this code with lambdas (as of Java 8), they make it possible to write the array generation, the print and the count routines in much less code. Like,
public class ArrayPractice {
private int[] arr;
private final int MAX_ARRAY_SIZE = 300;
private final int MAX_VALUE = 100;
public ArrayPractice() {
// randomly fill array with numbers
Random rand = new Random();
arr = IntStream.generate(() -> rand.nextInt(MAX_VALUE) + 1)
.limit(MAX_ARRAY_SIZE).toArray();
}
public void printArray() {
IntStream.of(arr).forEachOrdered(System.out::println);
}
public int countFrequency(int value) {
return (int) IntStream.of(arr).filter(i -> i == value).count();
}
}
You need to iterate over the array and increment a counter variable when an element matches i
what you are doing is increment i instead of a counter:
if (i == 8)
i++;
} // if i is 8 then i becomes 9
A working example:
public int countFrequency(int i) {
int count = 0;
for (int num : arr) {
if (num == i) {
count++;
}
}
return count;
}
Solution:
public int countFrequency(int value) {
int counter = 0; // here you will store counter of occurences of value passed as argument
for (int i : arr) { // for each int from arr (here was one of your errors)
if (i == value) // check if currently iterated int is equal to value passed as argument
counter++; // if it is equal, increment the counter value
}
return counter; // return the result value stored in counter
}
Explanation:
Main problem in your code was countFrequency() method, there are few bugs that you need to change if you want to make it work correctly:
You passed value as argument and you didn't even use it in the body of method.
for (int i : MAX_VALUE ) - you meant to iterate over elements of arr array, (You can read it then as: For each int from arr array do the following: {...}.
if (i == 8) i++ - here you said something like this: Check if the current element from array (assuming that you meant MAX_VALUE is an array) is equal to 8, and if it is - increment this value by 1 (so if it were 8, now it's 9). Your intention here was to increment counter that counts occurences of 8.
You might want to consider making these improvements to countFrequency() method, to make it work properly.

generating random numbers in java and finding percentage of how many are less than or equal to 50

My question is why isn't the code generating the amount of numbers that the users enters? Right now the code is only generating one number. Here is the original question given to me:
"In your main method, prompt the user for a number n. Write a method
called assessRandomness that generates a random number between 1 and
100 'n' times and return the percentage of times the number was less than
or equal to 50. Call your assessRandomness method from main and display
the result to the user from main. Do not interact with the user from
within the assessRandomness method."
output:
How many random numbers should I generate? 10
<assume the random numbers generated were 11 7 50 61 52 3 92 100 81 66>
40% of the numbers were 50 or less
my code:
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("how many random numbers should I generate?: ");
int number = in.nextInt();
assessRandomness(number);
}
public static double assessRandomness(int n){
int random = (int)(Math.random()*100);
int randomNumbersLessthan50 = 0;
if (random <= 50)
{
double getPercentage = random/randomNumbersLessthan50;
}
else
{
System.out.println(random);
}
return random;
}
I don't see any kind of loop within assessRandomness.
Try
for(int x = 1; x <= n; x++){ ... }
as first line in assessRandomness, it should finally look like
public static double assessRandomness(int n){
int counterLessThan50 = 0;
for ( int x = 1; x <= n; x++)
if( (int)(Math.random()*100) <= 50 ) counterLessThan50++;
return (double) counterLessThan50 / n;
}
There's no repetition in your code to do something n times.
Here's one way to do it in one line using a stream:
public static double assessRandomness(int n) {
return Stream.generate(Math::random).limit(n).map(r -> r * 100 + 1).filter(r -> r <= 50).count() / (double)n;
}
Note that converting Math.random() to a number in the range 1-100 is pointless; this will give the same result:
public static double assessRandomness(int n) {
return Stream.generate(Math::random).limit(n).filter(n -> n < .5).count() / (double)n;
}
And is easier to read.
At the moment, your assessRandomness method never uses the variable n.
At first you should initialize a variable which counts the number of created randoms that are bigger than 50 (this will be your retutn value). You should then do a loop from 0 until n. For each loop run you should create a random value between 0 and 100. Then you should check wether the value is bigger than 50. If so, count up your previously created variable. When the loop has finished, return the count variable and print it in the main method.
This should help you understand better how to do something like this.
public static void main(String[] args) {
System.out.println("how many random numbers should I generate?: ");
Scanner in = new Scanner(System.in);
int number = in.nextInt();
int[] arrayPlaceHolderInMainMethod = new int[number];
arrayPlaceHolderInMainMethod = generateRandomNumberArray(number);
assessRandomness(arrayPlaceHolderInMainMethod);
}
public static void assessRandomness(int[] inputArray) {
int randomNumbersLessthan50 = 0;
int randomNumbersGreaterthan50 = 0;
int random = 0;
for (int i = 0; i < inputArray.length; i++) {
random = inputArray[i];
}
if (random <= 50) {
randomNumbersLessthan50 += 1;
} else {
randomNumbersGreaterthan50 += 1;
}
System.out.println(">50: " + randomNumbersGreaterthan50 + " Less: " + randomNumbersLessthan50);
}
public static int[] generateRandomNumberArray(int numberPickedByUser) {
int[] arrayOfRandomNumbers = new int[numberPickedByUser];
for (int i = 0; i < numberPickedByUser; i++) {
arrayOfRandomNumbers[i] = (int) (Math.random() * 100 + 1);
}
return arrayOfRandomNumbers;
}

Trying to return sum of array, method call error

I am trying to return the sum of my array, however I instead of summing the array using recursion, the array sum just comes back as 0. I'm at that point where I think I may be overlooking something. An extra set of eyes would help out.
public class JavaSandbox {
/**
* #param args the command line arguments
*/
public static int sumDanceScore(int danceScore[], int first, int last)
{
if (first > last)
{
return 0;
}
else
{
int total = sumDanceScore(danceScore,first+1,last) + danceScore[first];
return total;
}
}
public static void main(String[] args)
{
Scanner kbd = new Scanner(System.in);
System.out.println("Enter number of contestants : ");
int numContest = kbd.nextInt();
int danceScore[] = new int[numContest + 1];
int first = 0;
int last = danceScore.length - 1;
System.out.println("Enter dance scores: ");
int numContestIndex;
for (numContestIndex = 1; numContestIndex <= numContest; numContestIndex++) {
danceScore[numContestIndex] = kbd.nextInt();
}
int danceScoreTotal = sumDanceScore(danceScore, first, last);
System.out.println("SUM DANCE SORE METHOD: "+danceScoreTotal);
for(int danceScoreIndex = 1; danceScoreIndex <= danceScore.length-1; danceScoreIndex++)
{
int danceScoreShare = danceScore[danceScoreIndex] / danceScoreTotal;
System.out.println("DANCE SCORE SHARE "+danceScoreShare);
}
}
}
In your code you invoke your function sumDanceScore before filling in the array. Thus, you pass an array filled with zeroes (as default values) to the function.
How to fix:
index first initialize to zero.
function sumDanceScore after filling in the array
How does recursion work on your sumDanceScore?
First, sumDanceScore is called for first == 0 and last == danceScore.length - 1 array. Then, the sumDanceScore leaves the initial element (in the first position) of the range and call next sumDanceScore with shifted position by one. This first == 1 and this variable is different from when calling sumDanceScore first time. Displace each time first, until first matches the last.
This is correct main body:
Scanner kbd = new Scanner(System.in);
System.out.println("Enter number of contestants : ");
int numContest = kbd.nextInt();
int danceScore[] = new int[numContest + 1];
int first = 0;
int last = danceScore.length - 1;
System.out.println("Enter dance scores: ");
int numContestIndex;
for (numContestIndex = 1; numContestIndex <= numContest; numContestIndex++) {
danceScore[numContestIndex] = kbd.nextInt();
}
int danceScoreTotal = sumDanceScore(danceScore, first, last);
System.out.println("SUM DANCE SORE METHOD: " + danceScoreTotal);

Why does the compiler give an " java.lang.ArrayIndexOutOfBoundsException: x -error? (size depends on input)

I am making a small program to guess the keylength of a vigenere-cipher, with a given length between 5-15, within java.
I do this by calculating standard deviations because of the transpositions.
But my real question is why I get an out of bound error in the array in the method "countFrequency". I can't seem to see where it goes out of bounds.
I know my program could be way more efficient, but I think it should work once this error is fixed.
My program code is below.
Thanks!
import java.awt.List;
import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
public class main {
// Scanning the encrypted text
// private static char encryptedText[];
public static void main(String[] args) throws IOException{
Scanner scan = null;new Scanner(System.in);
scan = new Scanner(System.in);
int i;
int vectors[][];
System.out.println("Give the decrypted text: \n");
String encryptedText = scan.next().toString();
vectors = makeArray();
vectors = countFrequency(vectors, encryptedText);
calculateDeviations(vectors);
// No need to scan more
if(scan!=null)
scan.close();
}
private static void calculateDeviations(int[][] vectors) {
int i;
int j;
int sumpowfreq;
int freqpowsum;
for(i=0;i<12;i++){
double deviation =0;
for(j=0; j<26;j++){
sumpowfreq = sumPowwFreq(vectors,i);
freqpowsum = freqPowwSum(vectors,i);
deviation = Math.sqrt((sumpowfreq/26) - (freqpowsum/26));
}
System.out.println("The devation of " + j + " is " + deviation + ".");
}
}
private static int freqPowwSum(int[][] vectors, int i) {
int powsum=0;
int sum=0;
int j;
for(j=0;j<26;j++){
sum = sum + vectors[j][i];
}
powsum = sum * sum;
return powsum;
}
public static int sumPowwFreq(int[][] vectors, int i) {
int sum=0;
int j;
for(j=0;j<26;j++){
sum = sum + (vectors[j][i] * vectors[j][i]);
}
return sum;
}
public static int[][] makeArray() {
// Making the 2-dimensional array and set it to 0
int keySize;
int letterFrequency[][] = new int[26][11];
for(keySize=5;keySize<16;keySize++){
int j;
for(j=0;j<26;j++){
letterFrequency[j][keySize-5] = 0;
}
}
return letterFrequency;
}
public static int[][] countFrequency(int freq[][], String encryptedText){
int i,j,c;
int splitSize;
int ascii;
String splittedText[];
for(splitSize=5; splitSize<15; splitSize++){
splittedText = splitText(splitSize, encryptedText);
for(j=0;j<splitSize;j++){
for(c=0;c<splittedText[j].length();c++){
ascii= splittedText[j].charAt(c);
ascii = ascii - 97; // because the ascii table starts at 97, 0 represents an 'a' now
// and we assumed that the encrypted text only contained small letters
freq[ascii][j]++;
}
}
}
return freq;
}
public static String[] splitText(int partLength, String encryptedText){
int len = encryptedText.length();
int amountparts = len / (partLength);
String parts[] = new String[amountparts];
// Break into parts
int offset= 0;
int i = 0;
while (i < amountparts){
parts[i] = encryptedText.substring(offset, Math.min(offset + partLength, len));
offset += partLength;
i++;
}
return parts;
}
}
I am no crypto-freak but I went into your code and saw the exception.
I think, your problem rather domain-specific than technical...
The nested for loops in countFrequency() expects the array splittedText to contain at least 15 elements.
for 1) splitSize runs from 5 to 14
for 2) for every splitSize,j runs
from 0 to splitSize
for 3) for every j, do something with the jth element of splittedText
The last for is important for the Exception:
splittedText must contain at least 15 elements.
How many elements are in splittedText?
This is determined in splitText(int, String). This method is called within (for 1) with the current splitSize as partLength and the user-input as encryptedText.
splitText returns an array with (encryptedText.length() / partlength) elements. So we have:
splittedText.length() = (inputlength / splitSize)
For every splitSize (5 to 14), the input-length must hold following condition:
input-length/splitSize >= splitSize ; and this is equivalent to
input-length >= splitSize * splitSize
for the splitSize of 14, your input must be greater than 196.
As far as I read, this is no constraint for vigenere-ciphers. And - btw - if you pass this first ArrayOutOfBoundException, you will run into the next Exception.

Using loops to compute factorial numbers, Java

I'm trying to compute the value of 7 factorial and display the answer, but when I tried to look up a way to do this I kept finding code that was written so that a number first had to be put in from the user and then it would factor whatever number the user put in. But I already know what number I need, obviously, so the code is going to be different and I'm having trouble figuring out how to do this.
I tried this at first
public class Ch4_Lab_7
{
public static void main(String[] args)
{
int factorial = 7;
while (factorial <= 7)
{
if (factorial > 0)
System.out.println(factorial*facto…
factorial--;
}
}
}
But all it does is display 7*7, then 6*6, then 5*5, and so on, and this isn't what I'm trying to do.
Does anyone know how to do it correctly?
import java.util.Scanner;
public class factorial {
public static void main (String[] args) {
Scanner input = new Scanner(System.in);
//Gives Prompt
System.out.print("Enter a number to find the factorial of it");
//Enter the times you want to run
int number = input.nextInt();
//Declares new int
int factor = 1;
//Runs loop and multiplies factor each time runned
for (int i=1; i<=number; i++) {
factor = factor*i;
}
//Prints out final number
System.out.println(factor);
}
}
Just keep multiplying it and until it reaches the number you inputted. Then print.
Input:5
Output:120
input:7
Output:5040
You need to have two variables, one for the factorial calculation and other for the purpose of counter. Try this, i have not tested it but should work:
public static void main(String[] args)
{
int input = 7;
int factorial = 1;
while (input > 0)
{
factorial = factorial * input
input--;
}
System.out.println("Factorial = " + factorial);
}
int a=7, fact=1, b=1;
do
{
fact=fact*b;//fact has the value 1 as constant and fact into b will be save in fact to multiply again.
System.out.print(fact);
b++;
}
while(a>=b); // a is greater and equals tob.
1st reason:
The methods you seen are probably recursive, which you seem to have edited.
2nd:
You are not storing, ANYWHERE the temporal results of factorial.
Try this
//number->n for n!
int number = 7;
//We'll store here the result of n!
int result = 1;
//we start from 7 and count backwards until 1
while (number > 0) {
//Multiply result and current number, and update result
result = number*result;
//Update the number, counting backwards here
number--;
}
//Print result in Screen
System.out.println(result);
Try this:
public static void main(String args[]) {
int i = 7;
int j = factorial(i); //Call the method
System.out.println(j); //Print result
}
public static int factorial(int i) { //Recursive method
if(i == 1)
return 1;
else
return i * factorial(i - 1);
}
This would print out the factorial of 7.
public class Factorial {
public static void main(String[] args) {
int result = factorial(5); //this is where we do 5!, to test.
System.out.println(result);
}
public static int factorial(int n) {
int x = 1;
int y = 1;
for (int i = 1; i <= n; i++) {
y = x * i;
x = y;
}
return y;
}
}
/*so, for 3! for example, we have:
i=1:
y = x * i, where x = 1, so that means:
y = 1*1 ; y= 1; x = y so x = 1. Then i increments =>
i = 2:
y = x * i. x is 1 and i is 2, so we have y = 2. Next step in code: x=y, means x = 2. Then i increments =>
i = 3:
y = x *i so we have y = 2*3. y=6. */

Categories

Resources