ArithmeticException division by zero... how to fix this method? - java

The purpose of this method is to iterate through a 2D array of integers called grid[][], and translate the integers based on the maximum and minimum values into a smaller range between 100 and 250 (the original minimum value becomes 100, the original maximum value becomes 250, and everything in between is calculated respectively). When this method is called, division by zero ArithmeticException occurs.
Clearly I'm making some logic mistakes here... I just don't see the fix. Can anyone help?
public int greenValues(int arrayVal) {
int max = 0;
int min = 0;
int colorValue = 0;
int temp;
for (int i = 0; i < grid.length; i++) { // finds maximum and minimum numbers in file
for (int j = 0; j < grid.length; j++) {
if (max < grid[i][j]) {
max = grid[i][j];
}
if (min > grid[i][j]) {
min = grid[i][j];
}
}
}
int arrayRange = (max-min); // arrayVal, arrayRange, and max and min are 0
temp = (((arrayVal-min) * COLOR_RANGE) / arrayRange) + 100; // map values to range of 100 - 250
colorValue = temp;
return colorValue;
}

This line is culprint for producing ArithmaticExcpetion.
temp = (((arrayVal-min) * COLOR_RANGE) / arrayRange) + 100;
your calculating arrayRange dynamically as you don't know when that value will be 0. so you can wrap this line with try catch block to do some exception handling.

Solution by Dilip is perfect. Or you can also add a conditional statement which lets it pass only when arrayRange is not 0 & execute something else if it is 0. But it'll increase overhead by executing the conditional statement every time arrayRange is calculated.

Related

Minimum Value in an Array java

I am working on a coding project where I have to have a user input five specific float values. Then based on those values I have to to get a total, maximum, minimum and then apply interest. I am stuck right now on getting the minimum value from the array. I have been able to get the maximum value but when I print the minimum value I get 0.0. Any ideas?
import java.util.Scanner;
public class float_assignment {
public static void main(String[] args) {
float[] userNum = new float[5];
float total = 0;
float average = 0;
float maximum = userNum[0];
float minimum = userNum[0];
float interest = 0;
int i = 0;
Scanner scnr= new Scanner(System.in);
for (i = 0; i <= 4; ++i) {
System.out.println("Please enter a number with a single decimal value:");
userNum[i] = scnr.nextFloat();
}
for (i = 0; i < userNum.length; ++i) {
if (userNum[i] > maximum) {
maximum = userNum[i];
}
}
for (i = 0; i < userNum.length; ++i) {
if(userNum[i] < minimum) {
minimum = userNum[i];
}
}
total = userNum[0] + userNum[1] + userNum[2] + userNum [3] + userNum [4];
System.out.println("");
System.out.println("Total value is: " + total);
System.out.println("");
System.out.println("Maximum Vaule is: " + maximum);
System.out.println("");
System.out.println("Minimum Vaule is: " + minimum);
}
}
The problem is with this
float[] userNum = new float[5];
.. //some other declarations
float minimum = userNum[0];
When you create an array of type float, all the elements are initialized to 0.0 (and it is obvious that you are inputting only positive numbers greater than 0)
See : java: primitive arrays — are they initialized?
To overcome this, initialize minimum (and maybe maximum too) after inputting the numbers from the console.
for(i = 0; i<=4; ++i) {
System.out.println("Please enter a number with a single decimal value:");
userNum[i]= scnr.nextFloat();
}
minimum = maximum = userNum[0];
//Proceed to find max and min
Note that you don't need two loops to find min and max and can combine them into one.
for(i = 0; i < userNum.length; ++i ) {
if(userNum[i]> maximum) {
maximum = userNum[i];
}
if(userNum[i] < minimum) {
minimum = userNum[i];
}
}
The issue is in the initial value of minimum. It's currently set at 0.
if(userNum[i] < minimum)
Will therefore never be true (assuming positive values). So you need to set the value of minimum to maximum just before you start the loop. Either that or set it to the max value allowed by float.
Java 8 version :
OptionalDouble min = IntStream.range(0, userNum.length).mapToDouble(i -> userNum[i]).min();
float minimum= (float) min.getAsDouble();
This is because in your initialization-
float userNum[] = new float[5];
Array userNum is by default being initialized with all zeros and it look like
userNum=[0.0,0.0,0.0,0.0,0.0]
And hence maximum and minimum are also initialized with 0.0
You might be entering all the positive values in the input that is why your maximum is showing correct but minimum remains 0.0
To avoid this initialize maximum and minimum with the first value of the array inside the for loop after it has been taken from the user.
Add this if statement inside your for loop of array assignmet
if(i==0)
{
maximum=minimum=userNum[0];
}
Please note that by convention, it is advised to begin your class-name with a capital letter. :)
Here, the logic you have applied is wrong. To make it work properly, you need to add another for loop inside your existing one. Then the value of variable 'minimum' must be updated during each iteration of your outer for loop and finally, place your if-condition inside inner for loop. Check the updated code given below:
for(i = 0; i< userNum.length; ++i) {
minimum = userNum[0]; //updating value at each iteration.
for(i = 0; i < userNum.length; ++i) { //newly added loop.
if(userNum[i] < minimum) {
minimum = userNum[i];
}
}
}

Finding max values of array 12 elements at a time

I have an array that has around 1000 entries, these are split up into 12 entries per year, I'm trying to find the maximum value for each year, to do so I need to read 12 values at a time and find the maximum value of those 12, and then move on to the next 12 values from the array, and so on until it is complete.
Trying to do this I made a temporary array to store the 12 values in, as well as the final array with the max score per year. The code below doesn't work and i'm unsure why, I have spent quite a while researching and attempting this with different solutions, any help will be appreciated :)
//double rain[]= new double [1268]; this is the array declared earlier with data in
double maxRAINyear[]= new double [1200];
double temp [] = new double [12];
int arrayCounter = 0;
int count = 0;
for (int c = 36; c < rain.length; c++) {
temp[count] = rain[c];
if (count == 12){
Arrays.sort(temp);
double max = temp[temp.length - 1];
maxRAINyear[arrayCounter] = max;
arrayCounter++;
count = 0;
}
count++;
}
It's difficult to see what's wrong with your code without knowing what it produces, but in any case this isn't a great way to do this.
I'll assume that you are constrained to the input format of one long array, even though a multidimensional array might make more sense depending on what else it's used for.
// double rain[] = new double[1268]; // input
double maxRAINyear[] = new double[(rain.length+11) / 12];
double max = Double.NEGATIVE_INFINITY;
for (int i = 0; i < rain.length; i++)
{
if (rain[i] > max) max = rain[i];
if (i % 12 == 0)
{
maxRAINyear[i / 12] = max;
max = Double.NEGATIVE_INFINITY;
}
}
if (rain.length % 12 != 0) maxRAINyear[maxRAINyear.length-1] = max;
This calculates the maximum of each 12 numbers as it goes, rather than storing them separately and sorting them. I've assumed there are a whole number of years stored. If you want to account for a partial year at the end this will need to be modified.
I implemented it without a temporary array, but by just iterating over the array. That should be more efficient.
int amountOfYears = rain.length/12-3;
double maxRAINyear[]= new double [amountOfYears];
for(int i=0;i<amountOfYears;i++){
//Find maximum for these 12 indixes
double max = Double.NEGATIVE_INFINITY;
for(int j=12*i+36;j<12*(i+1)+36;j++){ //use 12*i as an offset, that way, you don't need a temp array
if(rain[j] > max)
max = rain[j];
}
//store maximum
maxRAINyear[i] = max;
}
If you also need to find the partial year, use this
int amountOfYears = Math.ceil(rain.length/12f)-3;
double maxRAINyear[]= new double [amountOfYears];
for(int i=0;i<amountOfYears;i++){
//Find maximum for these 12 indixes
double max = Double.NEGATIVE_INFINITY;
int start = 12*i+36;
int end = Math.min(rain.length,12*(i+1)+36);
for(int j=start;j<end;j++){ //use 12*i as an offset, that way, you don't need a temp array
if(rain[j] > max)
max = rain[j];
}
//store maximum
maxRAINyear[i] = max;
}
When count is 11, you are incrementing it to 12 and going into the next round of the loop. Now temp[count] = rain[c]; will attempt to store a value into index 12 of temp, but there are only 12 entries with indices 0 through 11. So I suspect you are getting an ArrayIndexOutOfBoundsException.
I believe you should move count++ before the if statement. This way a count of 12 will be reset to 0 before it creates any havoc.
This solution have the advantage to work if the array length is not a multiple of the range without doing to many check.
public static double[] read(double[] array, int range) {
double[] result = new double[array.length / range + (array.length % range > 0 ? 1 : 0 )]; //Just add one cell if the length is not a multiple of the range
double max = array[0];
int i = 1;
while (i < array.length) {
if (i % range == 0) { //Next range
result[i / range - 1] = max; //Save last
max = array[i]; //Get current
} else if (array[i] > max) {
max = array[i];
}
++i;
}
result[result.length - 1] = max; //for the last range
return result;
}

in Java, design linear algorithm that finds contiguous subsequence with highest sum

this is the question, and yes it is homework, so I don't necessarily want anyone to "do it" for me; I just need suggestions: Maximum sum: Design a linear algorithm that finds a contiguous subsequence of at most M in a sequence of N long integers that has the highest sum among all such subsequences. Implement your algorithm, and confirm that the order of growth of its running time is linear.
I think that the best way to design this program would be to use nested for loops, but because the algorithm must be linear, I cannot do that. So, I decided to approach the problem by making separate for loops (instead of nested ones).
However, I'm really not sure where to start. The values will range from -99 to 99 (as per the range of my random number generating program).
This is what I have so far (not much):
public class MaxSum {
public static void main(String[] args){
int M = Integer.parseInt(args[0]);
int N = StdIn.readInt();
long[] a = new long[N];
for (int i = 0; i < N; i++) {
a[i] = StdIn.readLong();}}}
if M were a constant, this wouldn't be so difficult. For example, if M==3:
public class MaxSum2 {
public static void main(String[] args){
int N = StdIn.readInt(); //read size for array
long[] a = new long[N]; //create array of size N
for (int i = 0; i < N; i++) { //go through values of array
a[i] = StdIn.readLong();} //read in values and assign them to
//array indices
long p = a[0] + a[1] + a[2]; //start off with first 3 indices
for (int i =0; i<N-4; i++)
{if ((a[i]+a[i+1]+a[1+2])>=p) {p=(a[i]+a[i+1]+a[1+2]);}}
//if sum of values is greater than p, p becomes that sum
for (int i =0; i<N-4; i++) //prints the subsequence that equals p
{if ((a[i]+a[i+1]+a[1+2])==p) {StdOut.println((a[i]+a[i+1]+a[1+2]));}}}}
If I must, I think MaxSum2 will be acceptable for my lab report (sadly, they don't expect much). However, I'd really like to make a general program, one that takes into consideration the possibility that, say, there could be only one positive value for the array, meaning that adding the others to it would only reduce it's value; Or if M were to equal 5, but the highest sum is a subsequence of the length 3, then I would want it to print that smaller subsequence that has the actual maximum sum.
I also think as a novice programmer, this is something I Should learn to do. Oh and although it will probably be acceptable, I don't think I'm supposed to use stacks or queues because we haven't actually covered that in class yet.
Here is my version, adapted from Petar Minchev's code and with an important addition that allows this program to work for an array of numbers with all negative values.
public class MaxSum4 {
public static void main(String[] args)
{Stopwatch banana = new Stopwatch(); //stopwatch object for runtime data.
long sum = 0;
int currentStart = 0;
long bestSum = 0;
int bestStart = 0;
int bestEnd = 0;
int M = Integer.parseInt(args[0]); // read in highest possible length of
//subsequence from command line argument.
int N = StdIn.readInt(); //read in length of array
long[] a = new long[N];
for (int i = 0; i < N; i++) {//read in values from standard input
a[i] = StdIn.readLong();}//and assign those values to array
long negBuff = a[0];
for (int i = 0; i < N; i++) { //go through values of array to find
//largest sum (bestSum)
sum += a[i]; //and updates values. note bestSum, bestStart,
// and bestEnd updated
if (sum > bestSum) { //only when sum>bestSum
bestSum = sum;
bestStart = currentStart;
bestEnd = i; }
if (sum < 0) { //in case sum<0, skip to next iteration, reseting sum=0
sum = 0; //and update currentStart
currentStart = i + 1;
continue; }
if (i - currentStart + 1 == M) { //checks if sequence length becomes equal
//to M.
do { //updates sum and currentStart
sum -= a[currentStart];
currentStart++;
} while ((sum < 0 || a[currentStart] < 0) && (currentStart <= i));
//if sum or a[currentStart]
} //is less than 0 and currentStart<=i,
} //update sum and currentStart again
if(bestSum==0){ //checks to see if bestSum==0, which is the case if
//all values are negative
for (int i=0;i<N;i++){ //goes through values of array
//to find largest value
if (a[i] >= negBuff) {negBuff=a[i];
bestSum=negBuff; bestStart=i; bestEnd=i;}}}
//updates bestSum, bestStart, and bestEnd
StdOut.print("best subsequence is from
a[" + bestStart + "] to a[" + bestEnd + "]: ");
for (int i = bestStart; i<=bestEnd; i++)
{
StdOut.print(a[i]+ " "); //prints sequence
}
StdOut.println();
StdOut.println(banana.elapsedTime());}}//prints elapsed time
also, did this little trace for Petar's code:
trace for a small array
M=2
array: length 5
index value
0 -2
1 2
2 3
3 10
4 1
for the for-loop central to program:
i = 0 sum = 0 + -2 = -2
sum>bestSum? no
sum<0? yes so sum=0, currentStart = 0(i)+1 = 1,
and continue loop with next value of i
i = 1 sum = 0 + 2 = 2
sum>bestSum? yes so bestSum=2 and bestStart=currentStart=1 and bestEnd=1=1
sum<0? no
1(i)-1(currentStart)+1==M? 1-1+1=1 so no
i = 2 sum = 2+3 = 5
sum>bestSum? yes so bestSum=5, bestStart=currentStart=1, and bestEnd=2
sum<0? no
2(i)-1(currentStart)+1=M? 2-1+1=2 so yes:
sum = sum-a[1(curentstart)] =5-2=3. currentStart++=2.
(sum<0 || a[currentStart]<0)? no
i = 3 sum=3+10=13
sum>bestSum? yes so bestSum=13 and bestStart=currentStart=2 and bestEnd=3
sum<0? no
3(i)-2(currentStart)+1=M? 3-2+1=2 so yes:
sum = sum-a[1(curentstart)] =13-3=10. currentStart++=3.
(sum<0 || a[currentStart]<0)? no
i = 4 sum=10+1=11
sum>bestSum? no
sum<0? no
4(i)-3(currentStart)+1==M? yes but changes to sum and currentStart now are
irrelevent as loop terminates
Thanks again! Just wanted to post a final answer and I was slightly proud for catching the all negative thing.
Each element is looked at most twice (one time in the outer loop, and one time in the while loop).
O(2N) = O(N)
Explanation: each element is added to the current sum. When the sum goes below zero, it is reset to zero. When we hit M length sequence, we try to remove elements from the beginning, until the sum is > 0 and there are no negative elements in the beginning of it.
By the way, when all elements are < 0 inside the array, you should take only the largest negative number. This is a special edge case which I haven't written below.
Beware of bugs in the below code - it only illustrates the idea. I haven't run it.
int sum = 0;
int currentStart = 0;
int bestSum = 0;
int bestStart = 0;
int bestEnd = 0;
for (int i = 0; i < N; i++) {
sum += a[i];
if (sum > bestSum) {
bestSum = sum;
bestStart = currentStart;
bestEnd = i;
}
if (sum < 0) {
sum = 0;
currentStart = i + 1;
continue;
}
//Our sequence length has become equal to M
if (i - currentStart + 1 == M) {
do {
sum -= a[currentStart];
currentStart++;
} while ((sum < 0 || a[currentStart] < 0) && (currentStart <= i));
}
}
I think what you are looking for is discussed in detail here
Find the subsequence with largest sum of elements in an array
I have explained 2 different solutions to resolve this problem with O(N) - linear time.

How do I write a method to calculate the mode of an array?

I'm trying to write a method to calculate the mode of an array. I'm trying to write it with only two arrays. For some reason, the output I get is the size of the array --> 100. So far this is what I have:
public static int mode(int[ ] grades) {
int mode[ ] = new int [101];
int value = 0;
for (int i = 0; i < value; i++)
mode[grades[ i ] ]++; //this part really confuses me and I don't know how to interpret this.
//can someone please explain this to me too. I know this is the only...
int max = 0; //...way to get it with 2 arrays.
for(int i = 0; i < 101; i++) {
max = mode[ i ];
value = i;
}
return value;
}
grades can be in the range [0,100], which is 101 numbers (hence the size of 101).
for (int i = 0; i < value; i++)
mode[grades[i]]++;
grades[i] gets the number at slot i. Let's say that's 85. This give us:
mode[85]++, which increments the number of times we've seen the grade 85.
After this is complete, we iterate through mode and see which slot has the highest value, this value cooresponds to the mode, since mode simply keeps track of the number of times we encounter each score.
However, the second part is incorrect, you only want to update max, value if the current element is > max, ie:
int max = 0;
for(int i = 0; i< 101; i++)
{
if (mode[i] > max)
{
max = mode[i];
value = i;
}
}

BitSet(JAVA) is throwing outofBoundsException in the implementation of Sieve Of Eratosthenes

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.

Categories

Resources