works:meaning no precision error::Just array out of bounds
long a[] =new long[1000000];
int no=2,n;
long i;
a[no]=i+a[n];
if(a[no]>longChain)
{
longChain = a[no];
startNo = no;
}
and when I do
long a[] =new long[1000000];
long no=2,n;
long i,longChain=1,startNo;
a[no]=i+a[n];
if(a[no]>longChain)
{
longChain = a[no];
startNo = no;
}
then loss of precision
found:long
required: int
what is the problem?
My Code for above problem, its ProjectEuler Problem No. 14
class P14
{
public static void main(String args[])
{
long a[] =new long[1000000];
long no=2,n;
long i,longChain=1,startNo;
a[1]=1;
while(no<1000000)
{
n=no;
i=0;
while(n>no-1)
{
if(n%2==0)
n=n/2;
else
n=3*n+1;
i++;
//System.out.println(n);
}
a[no]=i+a[n];
if (a[no] > longChain)
{
longChain=a[no];
startNo=no;
}
no++;
//System.out.println(no);
}
}
}
This is my code for where above problem is occurring
Answer:: Replace a[no] by a[(int)n]
a[n],a[(int)n]
your no and n variables need to be int, not long. Arrays can't be indexed by long. Changing the code to:
int no=2,n;
makes the code compile.
The ArrayIndexOutOfBoundsException is because you wrote the algorithm assuming it was longs.
This code will eventually cause n to become negative:
n=3*n+1;
It's hard to see why when you're doing integer arithmetic. A slight change to make the code use long arithmetic and print the interim result reveals exactly when it becomes negative and how:
while(n>no-1)
{
long newN = n;
if (n % 2 == 0) newN = newN / 2L;
else newN = 3L * newN + 1L;
if (newN > Integer.MAX_VALUE) System.out.println("about to fail");
//this is where the magic happens
n = (int)newN;
System.out.println("converted " + newN + " to " + n);
i++;
}
This is likely because array indexing takes an int as the index. But all your variables are of type long.
a[no]
no is a long.
So using long as an array index is an implicit downcast which could result in loss of precision.
So either you manually cast it down, or you change no to an int.
EDIT: (after additional info in the question)
I'm not 100% sure if this is the cause:
n=3*n+1;
You use n as in index. But n can get pretty large to begin with. So a *3 could make it larger than the size of the array.
You should probably double-check whatever your algorithm is. (which I can't figure out from the code itself)
The problem you have is that you cannot store all the possible values you are calculating in array. Numbers can grow beyond 2^31-1 and you get an overflow.
What you can do is make
long n;
and
while (n > no - 1 || n >= a.length) {
}
// is safe as n < a.length;
a[no] = i + a[(int) n];
This ensures you only look up cached values which are inside your array.
n needs to be long because it may get too large for int. (If you use int it will overflow into negative numbers and cause the ArrayIndexOutOfBoundsException.)
You have to declare n as long and cast it to int when using it as index (no can be int)
a[no]=i+a[(int)n];
Related
I was trying to convert the array to integer sum=999999999999 (twelve 9) , when i am limiting the array to less than ten 9s it is giving the result but when i am giving the array of more than ten 9s it is giving an unexpected result , please explain it will be really helpful for me
int[] arr={9,9,9,9,9,9,9,9,9,9,9,9};
int p=arr.length-1;
int m;
int num=0;
for (int i = 0; i <= p; i++) {
m=(int) Math.pow(10, p-i);
num += arr[i]*m; // it is executing like: 900+90+9=999
}
this happens because you're exceeding the Integer.MAX_VALUE.
You can read about it here.
You can use instead of int a long, to store large values,
and if that is not enough for you, you can use - BigInteger
BigInteger num = BigInteger.valueOf(0);
for (int i = 0; i <= p; i++) {
BigInteger m = BigInteger.valueOf((int) Math.pow(10, p-i));
BigInteger next = BigInteger.valueOf(arr[i]).multiply(m));
num = num.add(BigInteger.valueOf(arr[i]*m));
}
A couple of things.
You don't need to use Math.pow.
for up to 18 digits, you can use a long to do the computation.
I added some extra digits to demonstrate
int[] arr={9,9,9,9,9,9,9,9,9,9,9,9,1,1,2,3,4};
long sum = 0; // or BigInteger sum = BigInteger.ZERO;
for (int val : arr) {
sum = sum * 10 + val; // or sum.multiply(BigInteger.TEN).add(BigInteger.valueOf(val));
}
System.out.println(sum);
prints
99999999999911234
Here is the sequence for 1,2,3,4 so you can see what is happening.
- sum = 0
- sum = sum(0) * 10 + 1 (sum is now 1)
- sum = sum(1) * 10 + 2 (sum is now 12)
- sum = sum(12)* 10 + 3 (sum is now 123)
- sum = sum(123)*10 + 4 (sum is now 1234)
It is because an int is coded on 4 byte so technically you can only go from -2,147,483,648 to 2,147,483,647.
Consider using the long type.
Try using long (or any other type which can represent larger numbers) instead of int.
I suggest this because the int overflows: see https://en.wikipedia.org/wiki/Integer_overflow
Because it overflows integer boundry. The maximum integer value that can be stored in Java is 2147483647. When you try to store a value greater than this, the result will be an unexpected value. To solve this issue, you can use a long data type instead of an int data type
you can read about it here and here
class TestClass {
public static void main(String args[] ) throws Exception {
long n = 1;
long ans = 1;
Scanner s = new Scanner(System.in);
long N = s.nextInt();
long M = 1000000007;
for (int i=1; i<=N; i++) {
ans = (ans*i) % M;
}
System.out.println(ans);
}
}
for 5! it is giving correct answer but when the value is more i am getting wrong output
Your long M = 1000000007; is buggy. (Is it a throwback to the old C ways of doing this for a narrower type?) Effectively a multiple of 1000000007 will be subtracted to pull a number greater or equal to that back into range: and the result of that will be nonsense.
Don't do that. Rely on Java to wrap-around for you as a last resort.
Then just adopt one of the rules of the long type: since the range of long is fixed in Java, the largest factorial number you can evaluate using that type is also fixed and happens to be 20!:
if (N > 20){
/*an overflow will occur so inform the user of your program*/
}
Do that and drop the M entirely.
Its basically depending on the number M with which you are doing modular operation. try by increasing M like long M = 100000000000007L will generate more valid factorial.
I have to print all the positive powers of integer k in the java long data type.
My code is:
int k = Integer.parseInt(args[0]);
int i = 1;
long a = k;
while (a <= Long.MAX_VALUE) {
System.out.print(i + " ");
System.out.println(a);
i++;
a = (long) Math.pow(k, i);
}
an infinite loop is created when i run this program.
But,when I run this program with a small change :(I have just removed the equals to operator in while condition)
int k = Integer.parseInt(args[0]);
int i = 1;
long a = k;
while (a < Long.MAX_VALUE) {
System.out.print(i + " ");
System.out.println(a);
i++;
a = (long) Math.pow(k, i);
}
It works fine as far as i think after that small change.
But,I am not able to understand what is happening here.
The issue is the cast from double to long following the Math.pow() call. doubles can hold much larger numbers than longs, and if you try to cast a large double to long, you'll get Long.MAX_VALUE. Your first loop will never exit, because all exponents after a certain point will just return Long.MAX_VALUE.
See for yourself:
public class DoubleToLong {
public static void main(String[] args) {
System.out.println((long)Double.MAX_VALUE);
System.out.println(Long.MAX_VALUE);
}
}
Returns:
9223372036854775807
9223372036854775807
The long data type is a 64-bit two's complement integer. if you check your results in both the cases, you will find at after certain number of iterations it reaches its max value, and subsequent iterations will restrict your calculation result to long's max value only. Hence <= condition will never be false because it will remain equal to long max.
When you remove equals condition, it will break after closest value it could reach towards long max.
Try with K as 2, that certain number of iteration is 63. (As long is 64 bit)
A silently overflows. Calculate the number of iterations up front instead and loop that number of times instead.
Let M(n,k) be the sum of all possible multiplications of k distinct factors with largest possible factor n, where order is irrelevant.
For example, M(5,3) = 225 , because:
1*2*3 = 6
1*2*4 = 8
1*2*5 = 10
1*3*4 = 12
1*3*5 = 15
1*4*5 = 20
2*3*4 = 24
2*3*5 = 30
2*4*5 = 40
3*4*5 = 60
6+8+10+12+15+20+24+30+40+60 = 225.
One can easily notice that there are C(n,k) such multiplications, corresponding to the number of ways one can pick k objects out of n possible objects. In the example above, C(5,3) = 10 and there really are 10 such multiplications, stated above.
The question can also be visualized as possible n-sized sets containing exactly k 0's, where each cell that does not contain 0 inside it, has the value of its index+1 inside it. For example, one possible such set is {0,2,3,0,5}. From here on, one needs to multiply the values in the set that are different than 0.
My approach is a recursive algorithm. Similiarly to the above definition of
M(n,k), I define M(n,j,k) to be the sum of all possible multiplications of exactly k distinct factors with largest possible factor n, AND SMALLEST possible factor j. Hence, my approach would yield the desired value if ran on
M(n,1,k). So I start my recursion on M(n,1,k), with the following code, written in Java:
public static long M (long n, long j, long k)
{
if (k==1)
return usefulFunctions.sum(j, n);
for (long i=j;i<=n-k+1+1;i++)
return i*M(n,i+1,k-1);
}
Explanation to the code:
Starting with, for example, n=5 , j=1, k=3, the algorithm will continue to run as long as we need more factors, (k>=1), and it is made sure to run only distinct factors thanks to the for loop, which increases the minimal possible value j as more factors are added. The loop runs and decreases the number of needed factors as they are 'added', which is achieved through applying
M(n,j+1,k-1). The j+1 assures that the factors will be distinct because the minimal value of the factor increases, and k-1 symbolizes that we need 1 less factor to add.
The function 'sum(j,n)' returns the value of the sum of all numbers starting from j untill n, so sum(1,10)=55. This is done with a proper, elegant and simple mathematical formula, with no loops: sum(j,n) = (n+1)*n/2 - (i-1)*i/2
public static long sum (long i, long n)
{
final long s1 = n * (n + 1) / 2;
final long s2 = i * (i - 1) / 2;
return s1 - s2 ;
}
The reason to apply this sum when k=1, I will explain with an example:
Say we have started with 1*2. Now we need a third factor, which can be either of 3,4,5. Because all multiplications: 1*2*3, 1*2*4, 1*2*5 are valid, we can return 1*2*(3+4+5) = 1*2*sum(3,5) = 24.
Similiar logic explains the coefficient "i" next to the M(n,j+1,k-1).
say we have now the sole factor 2. Hence we need 2 more factors, so we multiply 2 by the next itterations, which should result in:
2*(3*sum(4,5) + 4*sum(5,5))
However, for a reason I can't explain yet, the code doesn't work. It returns wrong values and also has "return" issues that cause the function not to return anything, don't know why.
This is the reason i'm posting this question here, in hope someone will aid me. Either by fixing this code or sharing a code of his own. Explaining where I'm going wrong will be most appreciable.
Thanks a lot in advance, and sorry for this very long question,
Matan.
-----------------------EDIT------------------------
Below is my fixed code, which solves this question. Posting it incase one should ever need it :) Have fun !
public static long M(long n, long j, long k)
{
if (k == 0)
return 0;
if (k == 1)
return sum(j,n);
else
{
long summation = 0;
for (long i=j; i<=n; i++)
summation += i*M(n, i+1, k-1);
return summation;
}
}
I see that u got ur answer and i really like ur algorithm but i cant control myself posting a better algorithm . here is the idea
M(n,k) = coefficient of x^k in (1+x)(1+2*x)(1+3*x)...(1+n*x)
u can solve above expression by divide and conquer algorithm Click Here to find how to multiply above expression and get polynomial function in the form of ax^n + bx^(n-1)....+c
overall algorithm time complexity is O(n * log^2 n)
and best part of above algorithm is
in the attempt of finding solution for M(n,k) , u will find solution for M(n,x) where 1<=x<=n
i hope it will be useful to know :)
I am not sure about your algorithm, but you certainly messed up with your sum function. The problem you have is connected to type casting and division of integer numbers. Try something like this:
public static long sum (long i, long n)
{
final long s1 = n * (n + 1) / 2;
final long s2 = (i * i - i) / 2;
return s1 - s2 ;
}
You have a problem with your sum function : here is the correct formula:
public static long sum (long i, long n)
{
double s1 = n*(n+1)/2;
double s2 = i*(i-1)/2;
return (long)(s1-s2);
}
Here the full solution :
static int n = 5;
static long k = 3;
// no need to add n and k them inside your M function cause they are fixed.
public static long M (long start) // start = 1
{
if(start > k) // if start is superior to k : like your example going from 1..3 , then you return 0
return 0;
int res = 0; // res of your function
for(long i=start+1;i<n;i++){
res+=start*i*sum(i+1,n); // here you take for example 1*2*sum(3,5) + 1*3*sum(4,5).... ect
}
return res+M(start+1); // return res and start again from start+1 wich would be 2.
}
public static long sum (long i, long n)
{
if(i>n)
return 0;
double s1 = n*(n+1)/2;
double s2 = i*(i-1)/2;
return (long)(s1-s2);
}
public static void main(String[] args) {
System.out.println(M(1));
}
Hope it helped
I have run into a weird issue for problem 3 of Project Euler. The program works for other numbers that are small, like 13195, but it throws this error when I try to crunch a big number like 600851475143:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at euler3.Euler3.main(Euler3.java:16)
Here's my code:
//Number whose prime factors will be determined
long num = 600851475143L;
//Declaration of variables
ArrayList factorsList = new ArrayList();
ArrayList primeFactorsList = new ArrayList();
//Generates a list of factors
for (int i = 2; i < num; i++)
{
if (num % i == 0)
{
factorsList.add(i);
}
}
//If the integer(s) in the factorsList are divisable by any number between 1
//and the integer itself (non-inclusive), it gets replaced by a zero
for (int i = 0; i < factorsList.size(); i++)
{
for (int j = 2; j < (Integer) factorsList.get(i); j++)
{
if ((Integer) factorsList.get(i) % j == 0)
{
factorsList.set(i, 0);
}
}
}
//Transfers all non-zero numbers into a new list called primeFactorsList
for (int i = 0; i < factorsList.size(); i++)
{
if ((Integer) factorsList.get(i) != 0)
{
primeFactorsList.add(factorsList.get(i));
}
}
Why is it only big numbers that cause this error?
Your code is just using Integer, which is a 32-bit type with a maximum value of 2147483647. It's unsurprising that it's failing when used for numbers much bigger than that. Note that your initial loop uses int as the loop variable, so would actually loop forever if it didn't throw an exception. The value of i will go from the 2147483647 to -2147483648 and continue.
Use BigInteger to handle arbitrarily large values, or Long if you're happy with a limited range but a larger one. (The maximum value of long / Long is 9223372036854775807L.)
However, I doubt that this is really the approach that's expected... it's going to take a long time for big numbers like that.
Not sure if it's the case as I don't know which line is which - but I notice your first loop uses an int.
//Generates a list of factors
for (int i = 2; i < num; i++)
{
if (num % i == 0)
{
factorsList.add(i);
}
}
As num is a long, its possible that num > Integer.MAX_INT and your loop is wrapping around to negative at MAX_INT then looping until 0, giving you a num % 0 operation.
Why does your solution not work?
Well numbers are discrete in hardware. Discrete means thy have a min and max values. Java uses two's complement, to store negative values, so 2147483647+1 == -2147483648. This is because for type int, max value is 2147483647. And doing this is called overflow.
It seems as if you have an overflow bug. Iterable value i first becomes negative, and eventually 0, thus you get java.lang.ArithmeticException: / by zero. If your computer can loop 10 million statements a second, this would take 1h 10min to reproduce, so I leave it as assumption an not a proof.
This is also reason trivially simple statements like a+b can produce bugs.
How to fix it?
package margusmartseppcode.From_1_to_9;
public class Problem_3 {
static long lpf(long nr) {
long max = 0;
for (long i = 2; i <= nr / i; i++)
while (nr % i == 0) {
max = i;
nr = nr / i;
}
return nr > 1 ? nr : max;
}
public static void main(String[] args) {
System.out.println(lpf(600851475143L));
}
}
You might think: "So how does this work?"
Well my tough process went like:
(Dynamical programming approach) If i had list of primes x {2,3,5,7,11,13,17, ...} up to value xi > nr / 2, then finding largest prime factor is trivial:
I start from the largest prime, and start testing if devision reminder with my number is zero, if it is, then that is the answer.
If after looping all the elements, I did not find my answer, my number must be a prime itself.
(Brute force, with filters) I assumed, that
my numbers largest prime factor is small (under 10 million).
if my numbers is a multiple of some number, then I can reduce loop size by that multiple.
I used the second approach here.
Note however, that if my number would be just little off and one of {600851475013, 600851475053, 600851475067, 600851475149, 600851475151}, then my approach assumptions would fail and program would take ridiculously long time to run. If computer could execute 10m statements per second it would take 6.954 days, to find the right answer.
In your brute force approach, just generating a list of factors would take longer - assuming you do not run out of memory before.
Is there a better way?
Sure, in Mathematica you could write it as:
P3[x_] := FactorInteger[x][[-1, 1]]
P3[600851475143]
or just FactorInteger[600851475143], and lookup the largest value.
This works because in Mathematica you have arbitrary size integers. Java also has arbitrary size integer class called BigInteger.
Apart from the BigInteger problem mentioned by Jon Skeet, note the following:
you only need to test factors up to sqrt(num)
each time you find a factor, divide num by that factor, and then test that factor again
there's really no need to use a collection to store the primes in advance
My solution (which was originally written in Perl) would look something like this in Java:
long n = 600851475143L; // the original input
long s = (long)Math.sqrt(n); // no need to test numbers larger than this
long f = 2; // the smallest factor to test
do {
if (n % f == 0) { // check we have a factor
n /= f; // this is our new number to test
s = (long)Math.sqrt(n); // and our range is smaller again
} else { // find next possible divisor
f = (f == 2) ? 3 : f + 2;
}
} while (f < s); // required result is in "n"