I've stumbled on the following problem: I have a class to get and print all primes between 1 and N. The N is a parameter which you have to insert by yourself. When I insert 10000 for N, the code works and prints out all primes out from 2 to the closest prime to N.
When I insert 40000 the code still works. When I insert 50000 (or higher), the code gives an ArrayOutOfBoundsException. Why?
This is the code I use:
ArrayList<Integer> priemGetallen = priemGetallen(n);
for (Integer i : priemGetallen) {
System.out.println(i);
}
And uses
ArrayList<Integer> priemgetallen = new ArrayList<Integer>();
for(int i = 2; i < n; i++){
priemgetallen.add(i);
}
for (int i = 2; i < n; i++) {
for (int j = i; j * i <= n; j++) {
if((j*i) < priemgetallen.size()){
priemgetallen.remove(j*i);
}
}
}
return priemgetallen;
}
The point "priemgetallen.remove(j*i)" is where I receive the error.
I'd really appreciate it if someone can tell me why this doesn't work for all N's bigger then approx. 40000.
Thanks in advance!
The maximum value a Java int can hold is 2,147,483,647, so j * i is overflowing when i and j reach 46,341.
To extend the range, change the types of i, j and n to long.
See How does Java handle integer underflows and overflows and how would you check for it?
P.S. You'll also need to change priemgetallen into an array list of Long rather than Integer.
Related
I have been trying to implement the given formula in JAVA but i was unsuccessful. Can someone help me find what I am doing wrong?
Do i need to shift the summation index and if so how?
My code:
public final class LinearSystem {
private LinearSystem() {
}
public static int[] solve(int [][]A , int []y) {
int n = A.length;
int[] x = new int[n];
for (int i = 0 ; i < n; i++) {
x[i] = 0;
int sum = 0;
for(int k = i + 1 ; k == n; k++) {
sum += A[i][k]*x[k]; // **java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3**
}
x[i] = 1/A[i][i] * (y[i] - sum);
}
return x;
}
public static void main(String[] args) {
int[][]A = new int[][]{{2,-1,-3},{0,4,-1},{0,0,3}};
int [] y = new int[] {4,-1,23};
System.out.println(Arrays.toString(solve(A,y))); **// awaited result [2, -3, 1]**
}
}
Just trying to collect all my comments under the question into one coherent answer, since there are quite a few different mistakes in your program.
This method of solving linear equations relies on your calculating the components of the answer in reverse order - that is, from bottom to top. That's because each x[i] value depends on the values below it in the vector, but not on the values above it. So your outer loop, where you iterate over the x values needs to start at the biggest index, and work down to the smallest. In other words, instead of being for (int i = 0; i < n; i++), it needs to be for (int i = n - 1; i >= 0; i++).
The inner loop has the wrong stopping condition. With a for loop, the part between the two semicolons is the condition to continue iterating, not the condition to stop. So instead of for(int k = i + 1; k == n; k++), you need for(int k = i + 1; k < n; k++).
You're doing an integer division at the beginning of 1 / A[i][i] * (y[i] - sum);, which means the value is rounded to an integer before carrying on. When you divide 1 by another integer, you always get -1, 0 or 1 because of the rounding, and that makes your answer incorrect. The fix from point 4 below will deal with this.
The formula relies on the mathematical accuracy that comes with working with either floating point types or decimal types. Integers aren't going to be accurate. So you need to change the declarations of some of your variables, as follows.
public static double[] solve(double[][] A, double[] y)
double x[] = new double[n];
double sum = 0.0;
along with the corresponding changes in the main method.
First, you need the second loop to go until k < n, otherwise this throws the ArrayOutOfBounds Exceptions.
Second, you need to calculate your x in reverse order as #Dawood ibn Kareem said.
Also, you probably want x[] to be a double-array to not only get 0-values as result.
I am sorry I don't know much about math side so I couldn't fix it to the right solution but I noticed a few things wrong about your code.
1-You shouldn't initialize your arrays as integer arrays, because you will be doing integer division all over the place. For example 1/A[i][i] will result in 0 even if A[i][i] = 2
2-You shouldn't write k == n, if you do it like this then your for loop will only execute if k equals n, which is impossible for your case.
I think you want to do k < n, which loops from i+1 to the point where k = n - 1
Here is my code:
import java.util.Arrays;
public final class LinearSystem {
private LinearSystem() {
}
public static double[] solve(double [][]A , double []y) {
int n = A.length;
double[] x = new double[n];
for (int i = 0 ; i < n; i++) {
x[i] = 0;
int sum = 0;
for(int k = i + 1 ; k < n; k++) {
sum += A[i][k] * x[k]; // **java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3**
}
x[i] = 1/A[i][i] * (y[i] - sum);
}
return x;
}
public static void main(String[] args) {
double[][]A = new double[][]{{2,-1,-3},{0,4,-1},{0,0,3}};
double [] y = new double[] {4,-1,23};
System.out.println(Arrays.toString(solve(A,y))); // awaited result [2, -3, 1]**
}
}
Remember that arrays are indexed from 0, so the last element is at index n - 1, not n.
public static void countingSort(Integer[] a, int n) {
//TODO
//COMPLETE THIS METHOD
int[] counter = new int[n+1];
int[] sorted = new int[a.length];
Arrays.fill(counter,0);
// fills counter array with each number count
for ( int i = 0 ; i < a.length; i++){
counter[a[i]] += 1;
} // adds n-1 index + n index
for (int i = 1; i < counter.length; i++) {
counter[i] = (counter[i] + counter[i-1]);
} // shifts array to the right
for (int i = counter.length-1; i > 0; i--) {
counter[i] = counter[i-1];
} // fills sorted array with the sorted out counts
for (int i = 0; i < a.length; i++ ){
sorted[counter[a[i]]] = a[i];
counter[a[i]]++;
}
}
When ran it throws an array out of bound exception in the body of the first for loop. Im having trouble seeing it, if anyone could help guide me, it'd be much appreciated.
When ran it throws an array out of bound exception in the body of the
first for loop.
That would be this:
for ( int i = 0 ; i < a.length; i++){
counter[a[i]] += 1;
}
Im having trouble seeing it, if anyone could help
guide me, it'd be much appreciated.
An ArrayIndexOutOfBoundsException in that loop can only mean that you are exceeding the bounds of a or those of counter. It is clear from inspection that you are not exceeding the bounds of a (though you could both eliminate that possibility and make the code a bit cleaner by switching to an enhanced for loop). The only remaining possibility is that you are exceeding the bounds of counter.
The approach you've implemented supports only non-negative integers in the input array, and requires the method invoker to pass an upper bound on the element values as the second parameter. If those constraints are not satisfied then an exception such as you observe will be thrown.
That is, if the exception is thrown where you say it is, then the problem is with the input.
I'm new to Java, and I'm trying to format an equation with int elements in an array (I keep getting the error "not a statement"). This is the bit of code:
int n = 0;
int[] time = {mins, mins2, mins3, mins4, mins5};
for(int j = 0; j <= 3; j++){
if (time[j] < time[j+1]){
n = time[j];
}
}
for(int k = 0; k <= 4; k++){
time[k] - n;
}
I found the smallest int (all elements are from a random number generator), and now I want to subtract the smallest from every element and permanently change the elements of the given array to those smaller numbers. I don't know how to format the "time[k] - n;" segment correctly.
Thank you for your help.
The line:
time[k] - n
Does nothing. It takes the value time[k] and subtracts the value n from it. It then discards the result.
What you want is to subtract n from the variable and assign the result back to the same variable:
time[k] = time[k] - n
In Java, this is equivalent to a compound assignment operator:
time[k] -= n
If you have Java 8 you could in fact do:
int[] time = {mins, mins2, mins3, mins4, mins5};
int min = IntStream.of(time).min().getAsInt();
int[] normalised = IntStream.of(time).map(i -> i - min).toArray();
And even with earlier versions of Java I would recommend:
int[] time = {mins, mins2, mins3, mins4, mins5};
int n = Integer.MAX_VALUE;
for (int t : time) {
n = Math.min(n, t);
}
for (int i = 0; i < time.length; ++i) {
time[i] -= n;
}
i.e. use a foreach loop where you can and otherwise use the length property of the array rather than hardcoding the length.
Change time[k] - n; to time[k] =- n;. So it will store time[k] - n in time[k]
Sorry,this is a homework problem. I am not good with maths, so I checked out some videos to understand how two matrices are multiplied. I came up with a formula, but I do not know what I am doing wrong? This question has been answered before, but I did not understand. Thank you.
case 3:
System.out.println("THE PRODUCT OF TWO MATRICES ARE: ");
for(i =0; i< arrayList.length; i++){
for(j =0; j< arrayList1.length; j++){
for(k =0; k < arrayList1.length;k++){
multiplication = arrayList[i][k] * arrayList1[k][j] + multiplication;
}
System.out.print(arrayList[i][j]+" ");
}
System.out.println();
}
break;
First of all you should understand that the multiplication of two matrices should result in a matrice (which not appear to be the case with your multiplication variable).
I suppose you have to program the basic implementation. Let's take a look at the following matrices.
A has n rows, and m columns; said to be a matrice n x m.
Similary, B has m rows and p columns (m x p matrice). The multiplication of A x B will give you a matrice n x p.
Note that if you want to do the multiplication A x B, the matrice A must have the same number of columns that the number of rows of the matrice B.
Now each value in the matrice AB (ith row and jth column) is computed as follow:
That said, let's take a look at the Java implementation (which is a pure translation of the mathematical formula).
public static int[][] multiply(int[][] matrixA, int[][] matrixB) {
int[][] result = new int[matrixA.length][matrixB[0].length];
for (int i = 0; i < result.length; i++) {
for (int j = 0; j < result[0].length; j++) {
for (int k = 0; k < matrixB.length; k++) {
result[i][j] += matrixA[i][k] * matrixB[k][j];
}
}
}
return result;
}
The result matrice is initialized at the right dimensions. Then the first two nested loop (with indices i and j) will loop through all the elements of elements of the resulting matrice. Then you just need the third loop to compute the sum.
You'd still need to check that the matrices you give as parameters have the correct length.
The algorithm used is pretty naive (O(n3) complexity). If you don't understand it, there's a lot of resources in the web that explains how it works; but that would more a mathematical question than a programming one.
Hope it helps ! :)
Here is my function for the implementation of Sieve Of Eratosthenes,
void solve() throws IOException {
int n = 200000;
ArrayList<Integer> primes = new ArrayList<Integer>();
BitSet bs = new BitSet(n + 1);
for(int i = 0; i <= n + 1; i++)
bs.set(i);
//setting bits at 0 and 1 to 0, since these are not considered as primes
bs.clear(0);
bs.clear(1);
for(int i = 2; i <= n + 1; i++) {
if(bs.get(i)) {
//cross out multiples of i starting from i*i (lesser one would have always been crossed out)
for(int j = i*i; j <= n + 1; j += i)
{
bs.clear(j);
}
primes.add(i); //add this prime to the list
}
}
for(int e : primes)
out.println(e);
}
When I run this I get and arrayOutOfBoundsException during the inner for loop, i.e.
for(int j = i*i; j <= n + 1; j += i)
{
bs.clear(j); //EXCEPTION is raised here
}
Error Message that I am getting is:
Exception in thread "main" java.lang.IndexOutOfBoundsException: bitIndex < 0: -2146737495
at java.util.BitSet.clear(BitSet.java:532)
at ERATOSTHENES.solve(ERATOSTHENES.java:45)
I dont understand where is the problem, if I reduce n to 20000, then my code works fine, but after n = 168000 (approx.), it shows this OutofBoundsException.
Is it something specific to BitSet, some property that I am not getting?
You are initialising (in the worst case) the variable i to be a large number close to 200,000 (specifically a large prime number?). That means j, which is initialised as i * i, will be in excess of 40,000,000,000, which is significantly over the max value of int (approx. 2,147,000,000) That means they will overflow over to negative values, which will definitely be out of range.
To solve the problem in this case, declare your variables to be of type long which is 64-bit and can hold much larger values.
You are getting an integer overflow in this line (i*i is negative):
for(int j = i*i; j <= n + 1; j += i)
Example:
System.out.println(168000 * 168000);
Prints:
-1840771072
Which is negative, so is less than n + 1 and passes cycle condition.
I think it could be because you are using an int and the number is getting too big i.e.
200,000 * 200,000 is a huge number and should probably be a long instead.