Getting ArrayIndexOutOfBoundsException after a Certain INPUT value - java

for the Given below code after int Input Value of 46348 i am getting ArrayIndexOutOfBoundsException. I am given Condition in for loop that keeps the array limits. But somehow i am getting this exception and i unable to figure it out. And my requirement is find all primenumbers below given number.
Scanner sc = new Scanner(System.in);
int n= sc.nextInt();
int[] arr= new int[n+1];
for(int i=2;i<=n;i++)
{
if(arr[i]==0)
{
for(j=i;j*i<=n;j++)
arr[j*i]=1; // Here i am getting Exception
}
}
Input:
46349
Output:
java.lang.ArrayIndexOutOfBoundsException: -2146737495
502802
Thanks.,

You have encountered an arithmetic overflow.
In Java, int data type is a 32-bit signed integer, which means it can have values between -2147483648 and 2147483647.
On this line:
for(j=i;j*i<=n;j++)
If i is 46349 then j becomes 46349, too. If you multiply 46349 by 46349, you get 2148229801, which is greater than 2147483647, so the integer overflows and becomes -2146737495. Naturally, it is less than 46349, so the check in the for-loop passes. But you cannot index an array with a negative value in Java, that's why you get the ArrayIndexOutOfBoundsException.
Range check your input value for n < 46340, or if it really needs to work with n = 46349 input, switch to long data type, which will work up to n = 3037000499.

46349 * 46349 is too big to use as the index of a Java Array. The index is just a 32-bit signed integer, so has a maximum value of 2,147,483,648.
It passes the < n check because it overflows and comes back negative, so it is in fact less than n, but a negative number is not a legal array index.

Related

How to convert decimal to binary in java

Most inputs to the program work fine but when i use large numbers e.g. 20 the value is incorrect. Is there a way I could convert the decimal numbers and output them as binary? Thank you.
int n = Comp122.getInt("What number would you like to make a factorial?");
int factorial = 1;
for (int i = 1 ; i<=n ; i++) {
factorial*=i;
System.out.println(factorial);
}
You’re encountering integer overflow at 13!, which exceeds the largest number that an int can hold, which is 231 (about 2.1 x 109).
You can change the type of your variable from int to long, which can hold 263 (about 1.9 x 1019), but that too will exceed its limit at 20!
To handle arbitrarily large numbers, use the BigInteger class as your variable type. Your code would then something like:
BigInteger factorial = BigInteger.ONE;
for (int i = 2; i < n; i++) {
factorial = factorial.multiply(néw BigInteger(i + ""));
}
By the way, to output an integer as binary or hex:
System.out.println(Integer.toBinaryString(n));
System.out.println(Integer.toHexString(n));
n! becomes very big and probably Integer cannot hold it as Integer has a limitation of 2,147,483,647.
That's not the problem of output, but rather you hit an overflow.
If you have a infinite range of input that could potentially fit in a BigInteger, you could try BigInteger. Otherwise, probably you'd like to use some unlimited data structure such as String. And do the calculation digit by digit.
Something like: https://www.geeksforgeeks.org/multiply-large-numbers-represented-as-strings/
20 the value is incorrect?
value of 20! = 2,432,902,008,176,640,000.
In java, an integer can properly handle any positive value less than 2,147,483,648.
int | 4 bytes | Stores whole numbers from -2,147,483,648 to 2,147,483,647
So, using int you can not handle this type of big value.
long datatype can be used for factorials only for n <= 20.
For larger values of n, we can use the BigInteger class from the java.math package, which can hold values up to 2^Integer.MAX_VALUE:

Divisor value in for loop is mysteriously (?) changing

So I have been at this for hours, and I'm honestly completely stuck. I've wrote a for loop that counts the amount of numbers in an integer, but I've found that the divisor value changes once i enter a number above 10 digits, and I can't figure out why. I've searched the internet to no avail, so I would appreciate any help or tips if you have any. Thank you!
public static int getNumberOfDigits(long creditCardNumber)
{
//problem with 0's at beginning and more than 10 digits
int nDigitsInCard = 0;
int divisor = (int) creditCardNumber;
for(int i = 0; i <= creditCardNumber; i++){
while(divisor!=0){
divisor/=10;
++nDigitsInCard;
}
}
// return the number of digits in nDigitsInCard
return nDigitsInCard;
}
ints can't hold numbers greater than 2,147,483,647. You need to stick to longs to work with larger numbers.
Integers can only hold numbers up to 2 ^ 32 - 1. Also, why are you casting the input parameter to an integer?
Another thing is that you are counting the number of digits in every number leading up to divisor since you are looping from 0 all the way up to creditCardNumber in the for(int i = 0; i <= creditCardNumber; i++){ ... }. So for example 10000 would return the number of digits in 1, the number of digits in 2, all the way up to 10000.
Lastly, the whole function can be done in one line with
return Long.toString(creditCardNumber).length();
or
return creditCardNumber.toString().length();
if you change creditCardNumber to a Long instead of a long, but you would have to call it with an l suffix at the end.
If you want something even shorter, you can do
return (creditCardNumber+"").length();
When you have the number greater than 10 digits, the conversion to an integer doesn't complete because the integer can't hold valures greater than 2^31 - 1, or 2,147,483,647, which is a number with only 10 digits. I recommend sticking with long.

Array Duplicate Efficiency Riddle

Recently in AP Computer Science A, our class recently learned about arrays. Our teacher posed to us a riddle.
Say you have 20 numbers, 10 through 100 inclusive, right? (these numbers are gathered from another file using Scanners)
As each number is read, we must print the number if and only if it is not a duplicate of a number already read. Now, here's the catch. We must use the smallest array possible to solve the problem.
That's the real problem I'm having. All of my solutions require a pretty big array that has 20 slots in it.
I am required to use an array. What would be the smallest array that we could use to solve the problem efficiently?
If anyone could explain the method with pseudocode (or in words) that would be awesome.
In the worst case we have to use an array of length 19.
Why 19? Each unique number has to be remembered in order to sort out duplicates from the following numbers. Since you know that there are 20 numbers incoming, but not more, you don't have to store the last number. Either the 20th number already appeared (then don't do anything), or the 20th number is unique (then print it and exit – no need to save it).
By the way: I wouldn't call an array of length 20 big :)
If your numbers are integers: You have a range from 10 to 100. So you need 91 Bits to store which values have already been read. A Java Long has 64 Bits. So you will need an array of two Longs. Let every Bit (except for the superfluous ones) stand for a number from 10 to 100. Initialize both longs with 0. When a number is read, check if the corresponding bit mapped to the read value is set to 1. If yes, the read number is a duplicate, if no set the bit to 1.
This is the idea behind the BitSet class.
Agree with Socowi. If number of numbers is known and it is equal to N , it is always possible to use N-1 array to store duplicates. Once the last element from the input is received and it is already known that this is the last element, it is not really needed to store this last value in the duplicates array.
Another idea. If your numbers are small and really located in [10:100] diapason, you can use 1 Long number for storing at least 2 small Integers and extract them from Long number using binary AND to extract small integers values back. In this case it is possible to use N/2 array. But it will make searching in this array more complicated and does not save much memory, only number of items in the array will be decreased.
You technically don't need an array, since the input size is fixed, you can just declare 20 variables. But let's say it wasn't fixed.
As other answer says, worst case is indeed 19 slots in the array. But, assuming we are talking about integers here, there is a better case scenario where some numbers form a contiguous interval. In that case, you only have to remember the highest and lowest number, since anything in between is also a duplicate. You can use an array of intervals.
With the range of 10 to 100, the numbers can be spaced apart and you still need an array of 19 intervals, in the worst case. But let's say, that the best case occurs, and all numbers form a contiguous interval, then you only need 1 array slot.
The problem you'd still have to solve is to create an abstraction over an array, that expands itself by 1 when an element is added, so it will use the minimal size necessary. (Similar to ArrayList, but it doubles in size when capacity is reached).
Since an array cannot change size at run time You need a companion variable to count the numbers that are not duplicates and fill the array partially with only those numbers.
Here is a simple code that use companion variable currentsize and fill the array partially.
Alternative you can use arrayList which change size during run time
final int LENGTH = 20;
double[] numbers = new double[LENGTH];
int currentSize = 0;
Scanner in = new Scanner(System.in);
while (in.hasNextDouble()){
if (currentSize < numbers.length){
numbers[currentSize] = in.nextDouble();
currentSize++;
}
}
Edit
Now the currentSize contains those actual numbers that are not duplicates and you did not fill all 20 elements in case you had some duplicates. Of course you need some code to determine whither a numbers is duplicate or not.
My last answer misunderstood what you were needing, but I turned this thing up that does it an int array of 5 elements using bit shifting. Since we know the max number is 100 we can store (Quite messily) four numbers into each index.
Random rand = new Random();
int[] numbers = new int[5];
int curNum;
for (int i = 0; i < 20; i++) {
curNum = rand.nextInt(100);
System.out.println(curNum);
boolean print = true;
for (int x = 0; x < i; x++) {
byte numberToCheck = ((byte) (numbers[(x - (x % 4)) / 4] >>> ((x%4) * 8)));
if (numberToCheck == curNum) {
print = false;
}
}
if (print) {
System.out.println("No Match: " + curNum);
}
int index = ((i - (i % 4)) / 4);
numbers[index] = numbers[index] | (curNum << (((i % 4)) * 8));
}
I use rand to get my ints but you could easily change this to a scanner.

Converting byte array to integer - last value always converts to zero

When converting my byte array to an integer array for calculations, the integer array should be the same values as the byte array. However, in my integer array, the last array value always outputs as zero.
for (int i = 0; i < arrCalc.length; intArray[i] = arrCalc[i++])
In this case, the arrCalc values are [97,98,99], and after the above code runs, intArray is showing [97,98,0] instead of [97,98,99]. Can anyone explain why this is and/or how to fix it?
*Note - I generally don't program in Java...if that matters at all...
The problem is your postfix. It is processed before you think it is.
Try breaking the code (besides, it is more Java-style compliant):
for (int i = 0; i < arrCalc.length; i++) {
intArray[i] = arrCalc[i];
}
Oracle Site about Operator Precedence
The operators in the following table are listed according to
precedence order. The closer to the top of the table an operator
appears, the higher its precedence.

When I multiply the numbers by each other in an array I am getting a negative number. How do I correct this?

public static void main(String[]args){
int A[]={2,4,6,9,5,4,5,7,12,15,21,32,45,5,6,7,12};
int multi= 1;
for (int i=0; i<A.length; i++) {
multi *= A[i];
}
System.out.println("The product of the numbers in the array is " + multi );
//I keep getting a negative value but when I shorten the array
//to a few numbers I don't have any problems.
}
That's called overflow.
An integer overflow occurs when an arithmetic operation attempts to create a numeric value that is too large to be represented within the available storage space. [Wikipedia - Integer Overflow]
ints can represent a maximum of (2^32)-1. Your multiplication gives a result that is higher than that value, so it generates overflow.
Change multi type to long and you won't have this problem (but only for that particular case: if you exceed the maximum value representable by a long, you'll have that problem again)
As said, changing the type to long will only postpone the problem, you can solve it by using a BigInteger, which can handle arbitrary-precision integers.
But use it only if you really have to. If you know that your app will do calculations without exceeding the long max representable value, then use a long, as the BigInteger is not a primitive and will be much slower than a long.
Start by declaring multi as a long. When a value exceeds Integer.MAX_VALUE i 'overflows' and becomes negative. The maximum integer value is just more than 2 billion, so it happens quite soon.
You encounter a negative value, it is because the multi value exceeds the Max value of Integer (2^31 -1).
You need to make the change as follows:
From
int multi= 1;
To
long multi= 1;
try this
public static void main(String[]args){
int A[]={2,4,6,9,5,4,5,7,12,15,21,32,45,5,6,7,12};
long multi= 1;
for (int i=0; i<A.length; i++) {
multi *= A[i];
}
System.out.println("The product of the numbers in the array is " + multi );
//I keep getting a negative value but when I shorten the array
//to a few numbers I don't have any problems.
}

Categories