How to convert equation from long to Biginteger - java

So I am doing this problem which requires to calculate the equations. At first i thought long would be enough for the range but now it has exceeded the long range and now i have to use BigInteger. I have to convert one equation but I haven't been able to
This is the equation :
count =(n2/n3)-((n1-1)/n3);
Count can be long but n1,n2,n3 should be BigInteger.

This simplifies to:
-(n1-n2-1)/n3
and in Java
BigInteger count = n1
.subtract(n2)
.subtract(BigInteger.valueOf(1))
.negate()
.divide(n3)

BigInteger seems to have a longValue() method that should be able to do the job:
http://docs.oracle.com/javase/7/docs/api/java/math/BigInteger.html
long count = (n2
.divide(n3))
.substract( (n1
.subtract(BigInteger.ONE))
.divide(n3)
).longValue()

This oneliner should do the trick...
long count;
BigInteger n1, n2, n3;
n1 = n2 = n3 = new BigInteger("1231232");
//count =(n2/n3)-((n1-1)/n3);
//count = (n2/n3)
count = (n2.divide(n3))
// -
.subtract(
//((n1-1)/n3);
((n1.subtract(new BigInteger("1").divide(n3))))
).longValue();

You can use BigInteger#valueOf(long val)
count = (BigInteger.valueOf(n2.intValue()).divide(BigInteger.valueOf(n3.intValue()))).
subtract(((BigInteger.valueOf(n1.intValue()).
subtract(BigInteger.valueOf(n1.intValue()))).
divide(BigInteger.valueOf(n3.intValue())));

Related

Multiplication overflow problem in int and long in java

Multiplication of 123456789 and 987654321 is yielding in -67153019. I have used both int and long types but couldn't find the required result.
int n1 = 123456789 ;
int n2 = 987654321 ;
long ans = n1*n2 ;
The result should be 121932631112635269 but it comes out to be -67153019.
This is because 121932631112635269 is greater than max int, so when doing n1 * n2, the result parsed to int will be garbage. The cast to Long is made after the math, when it tries to do the = with ans.
If you cast n1 and n2 to long before, doing the math you will get 121932631112635269.
int n1 = 123456789 ;
int n2 = 987654321 ;
long ans = (long)n1 * (long)n2;
or like this:
int n1 = 123456789 ;
int n2 = 987654321 ;
long ans = 1L * n1 * n2;
or if you change n1 and n2 types to long
edit: as Turing85 says,
the 2nd cast is superfluous
since the n1 would be cast to long before, there's no need to cast n2, since the result would be a Long. Making:
int n1 = 123456789 ;
int n2 = 987654321 ;
long ans = (long)n1 * n2;
also correct
It is due to order of operations. In your case, first JVM tries to multiply 2 ints as an int (because result of binary operation with int operands is also an int), and only then puts the result to long because the left-hand side variable has long type.
Please try this:
long ans = 1L * n1 * n2;
This should solve the overflow issue.

Array form of integer

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

How to get all digit summation in BigInteger Value?

I have the following problem:
If n1 & n2 are natural numbers while n1 < 10 and n2 <10000.
find the summation of all digits in z where z = n1n2.
ex. n1 = 3, n2 = 10, z= 3^10 = 59049 if you sum the digits 5+9+0+4+9= 27. result =27
ex. n1 = 2, n2 = 12, z= 2^12 = 4096 if you sum the digits 4+0+9+6 = 19. result =19
And my current solution is:
public static long Solving(int n1, int n2) {
if (n1 >= 0 && n2 >= 0) {
BigInteger z = BigInteger.valueOf((long) Math.pow(n1, n2));
long sum = 0;
for (BigInteger i = z; i.compareTo(BigInteger.ZERO) > 0; i = i.divide(BigInteger.TEN)) {
sum += Integer.valueOf(String.valueOf(i.remainder(BigInteger.TEN)));
}
return sum;
}
return 0;
}
Why all cases doesn't success in that problem?
The actual problem is Math.pow(n1, n2).
Here you are treating both arguments as double and trying to calculate n1n2 which can easily cause an overflow.
Instead you can use BigInteger#pow() to get rid of overflow:
BigInteger z = BigInteger.valueOf(n1).pow(n2);
This will solve the issue.
I think you can solve this easily by doing something like this :
Step 1. Convert n1 to BigInteger
Step 2. Use native power function of BigInteger [exponent of pow function of big integer must be int]
Step 3. Convert the result back into string
Step 4. Iterate over the string and calculate the sum of digits.
Reference : https://www.tutorialspoint.com/java/math/java_math_biginteger.htm
https://www.tutorialspoint.com/java/math/biginteger_pow.htm

ArrayIndexOutOfBounds after solving 'possible loss of precision' compile error

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];

What should be the optimal way to find the average of a large number of integers?

Each of the integers can be as large as the size of an integer itself (Java int-32 bits), so storing the sum of the integer numbers in an integer variable isn't an option.
I'm afraid using Java BigInts might affect the performance badly.
Right now I'm trying divide and conquer while using long to store the sum.
Are there any better solutions?
You can use long (64-bit) to hold the sum. If you overrun that, BigInteger is the way to go.
BigInt is pretty fast. As I always say, do it right first, profile and optimize later.
How about long datatype? It should be pretty fast even on 32-bit machines.
You can use floats and then convert the result back into a integer. That might not be optimal but should be fast enough (and straight forward)
If you know the number of ints you'll have to average in advance, you can do the division one-by-one
int [] a;
int average;
int remainder;
int alen = a.length;
for( int i = 0; i < alen; i++ ) {
int q = a[i] / alen; //calculate the quotient and the remainder for the current element
int r = a[i] % alen;
average += q; // add up the averages and the remainders
remainder += r;
if( remainder >= alen ) { //roll the average over if needed
remainder -= alen;
average++;
}
}
Of course in practice it doesn't matter because you can't have more than 231 elements in an array, which means you could store the sum in a long.
Unless you're calculating the average of billions of numbers, using BigInteger shouldn't have much of an effect on performance. You should try coding it with BigInteger and then decide if it's fast enough.
You can store above 2billions of ints in a long. What's the problem?
Well, if you need even more ints. Do a simple class holding multiple longs (and long[] will do), and add on top of the 1st. Each 2billions of adds, get a fresh new long.
In the end (avg) sum the longs in a BigInteger and divide. The code has close to no overhead, one extra counter and one extra check (that's branch predicted).
[hopefully I didn't make some stupid off by 1 ;) ]
package t1;
import java.math.BigInteger;
import java.util.Arrays;
public class Avg {
long sum;
long[] totals = new long[0];
int counter;
public void add(int v){
if (counter++==Integer.MAX_VALUE){
counter = 0;
int len =totals.length;
totals = Arrays.copyOf(totals, len+1);
totals[len]=sum;
sum = 0;
}
sum+=v;
}
public int avg(){
long count = this.counter;
count+=totals.length*(long)Integer.MAX_VALUE;
BigInteger sum = BigInteger.valueOf(this.sum);
for (long subSum : totals)
sum=sum.add(BigInteger.valueOf(subSum));
return sum.divide(BigInteger.valueOf(count)).intValue();//tweak if you need be
}
}

Categories