Is there a Math.floorDiv(a, b), but for BigInteger? - java

Some way to make a Math.floorDiv(a, b); and return the floor division of two BigInteger values
An example:
BigInteger big0 = new BigInteger("10");
BigInteger big1 = new BigInteger("20");
Math.floorDiv(big0, big1);

Switch to BigDecimal and you can control rounding. A scale of 0 means the results are rounded to an integer and FLOOR rounds towards negative infinity.
big0.divide(big1, 0, RoundingMode.FLOOR)
(If you construct big0 from an int, long, or BigInteger then its scale will already be 0 and you can omit the middle argument.)

No such method exists in the BigInteger API.
However, you could implement it using BigInteger::divideAndRemainder (javadoc) and adjusting the result to be analogous to the Math::floorDiv spec. Something like this:
BigInteger a = new BigInteger("10");
BigInteger b = new BigInteger("20");
BigInteger c = floorDiv(a, b);
public BigInteger floorDiv(BigInteger a, BigInteger b) {
// divideAndRemainder returns quotient and remainder in array
BigInteger[] qr = a.divideAndRemainder(b);
return qr[0].signum() >= 0 || qr[1].signum() == 0 ?
qr[0] : qr[0].subtract(BigInteger.ONE);
}

Based on Math.floorDiv:
public static BigInteger floorDiv(final BigInteger x, final BigInteger y) {
if (x.signum() * y.signum() >= 0) {
return x.divide(y);
}
final BigInteger[] qr = x.divideAndRemainder(y);
return qr[1].signum() == 0 ? qr[0] : qr[0].subtract(BigInteger.ONE);
}

Related

BigInteger Performance

public static BigInteger find(BigInteger A,BigInteger B)
{
BigInteger res=BigInteger.ONE;
for(BigInteger i=A;i.compareTo(B)!=0;i.add(BigInteger.ONE))
res=res.add(i);
/*for(BigInteger i=1;i.compareTo(B)!=0;i.add(BigInteger.ONE))
res=res.multiply(A);*/
return res;
}
my intention is to add any 2 numbers within the range., let's say 2 to 5(2+3+4+5) or A raise to B. I have other option to get it done within BigInteger, but can anybody say what's wrong with the above snippet in which
Its producing longggggggggggggggggggggggggggggggg strange number(instead of original) and
Its struggling/juggling so much to increment by 1 as it normally increment outside/without loop?
When will it reach just one increment(time or space factor/performance)?
The sum of all integers in a range can be calculated as the average value multiplied by the number of values, aka the "count".
If A and B are both inclusive, as indicated by the "2 to 5(2+3+4+5)" text in the question, then we have:
average = (A + B) / 2
count = B - A + 1
sum = count * average
= (B - A + 1) * ((A + B) / 2)
= (B - A + 1) * (B + A) / 2 // flipped A + B for the symmetry of it
In Java code, using BigInteger, that means:
public static BigInteger sumRangeInclusive(BigInteger A, BigInteger B) {
return B.subtract(A).add(BigInteger.ONE).multiply(B.add(A)).shiftRight(1);
}
It seems there is an issue with storing value of the loop variable after increment.
The sum of arithmetic progression should include both A and B:
public static BigInteger find(BigInteger A,BigInteger B)
{
BigInteger sum = BigInteger.ZERO;
for (BigInteger i = A; i.compareTo(B) <=0; i = i.add(BigInteger.ONE)) {
sum = sum.add(i);
}
return sum;
}
Tests:
System.out.println(find(new BigInteger("2"), BigInteger.valueOf(5)));
System.out.println(find(new BigInteger("200"), BigInteger.valueOf(500)));
Output:
14
105350
my option for A raises to B without generating multiple instances
public static BigInteger find(BigInteger A,BigInteger B)
{
BigInteger res=BigInteger.ONE;
int b=B.intValue();
for(int i=1;i<=b;i++)
res=res.multiply(A);
return res;
}
A better way to solve this would be by applying simple arithmetic. We know that:
Sum of natural numbers up to n = n * (n + 1) / 2
Sum of natural numbers from m to n = Sum of natural numbers up to n minus Sum of natural numbers up to m - 1 = n * (n + 1) / 2 - (m - 1) * (m - 1 + 1) / 2 = n * (n + 1) / 2 - (m - 1) * (m) / 2 = (n * (n + 1) - (m - 1) * m) / 2.
Demo:
import java.math.BigInteger;
public class Main {
public static void main(String[] args) {
System.out.println(find(BigInteger.valueOf(123456789), BigInteger.valueOf(987654321)));
}
public static BigInteger find(BigInteger A, BigInteger B) {
return B.multiply(B.add(BigInteger.ONE)).subtract(A.subtract(BigInteger.ONE).multiply(A))
.divide(BigInteger.TWO);
}
}
Output:
480109740075445815
What is wrong with your code?
The loop terminates when A becomes equal to B whereas it should terminate when A becomes greater than B. For this, you can use the terminating condition as i.compareTo(B.add(BigInteger.ONE)) != 0.
A BigInteger is an immutable arbitrary-precision integer. Therefore, i.add(BigInteger.ONE) won't modify the value of i. You need to assign the result to i i.e. i = i.add(BigInteger.ONE) in order to increment the value referenced by i by one.
You have started with a value 1 (i.e. BigInteger res=BigInteger.ONE) instead of 0.
Correct code:
import java.math.BigInteger;
public class Main {
public static void main(String[] args) {
System.out.println(find(BigInteger.valueOf(2), BigInteger.valueOf(5)));
}
public static BigInteger find(BigInteger A, BigInteger B) {
BigInteger res = BigInteger.ZERO;
for (BigInteger i = A; i.compareTo(B.add(BigInteger.ONE)) != 0; i = i.add(BigInteger.ONE))
res = res.add(i);
return res;
}
}
Output:
14
Although you can get the correct result after correcting your code this way, it's performance will be extremely bad.

Karatsuba multiplication not working recursively with BigInteger

I am trying to multiply n digit number using karatsuba multiplication.
I am getting output for single digit number (Example 4 and 5 = 20).
But, when I multiply 1234 and 5678 I am getting error and no output result.
I have updated the code and error message. Please check.
The error is Click here
import java.math.BigInteger;
class karatsubamultiplication{
public static BigInteger karat(BigInteger number1, BigInteger number2){
if(number1.bitLength() < 4 && number2.bitLength() < 4)
return number1.multiply(number2);
//Finding maximum length of two
//int m = Math.max(number1, number2);
String first = number1.toString();
String second = number2.toString();
BigInteger a = new BigInteger(first.substring(0, first.length()/2));
BigInteger b = new BigInteger(first.substring(first.length() - first.length()/2, first.length()));
BigInteger c = new BigInteger(second.substring(0, second.length()/2));
BigInteger d = new BigInteger(second.substring(second.length() - second.length()/2, second.length()));
BigInteger ac = karat(a, c);
BigInteger bd = karat(b, d);
BigInteger abcd = karat(a.add(b), c.add(d));
BigInteger z = abcd.subtract(ac.add(bd));
int m = String.valueOf(number1).length();
BigInteger len = new BigInteger(String.valueOf(Math.pow(10, m)));
return (ac.multiply(len)).add(z.multiply(len.divide(BigInteger.valueOf(2)))).add(bd);
}
public static void main(String[] args){
BigInteger result = new BigInteger("0");
BigInteger x = new BigInteger("1234");
BigInteger y = new BigInteger("5678");
result = karat(x, y);
System.out.println(result);
}
}
Please correct the code. I have not checked whether two numbers are equal or not and length is odd or even.
Thank you.

Int to BigInteger, what's the difference?

I transfer the modExp function from int to BigInteger, but the result is different, what the different of these two functions?
Thanks!!!
The function with BigInteger, the result always 1:
public static BigInteger modExp(BigInteger a, BigInteger b, BigInteger n) {
BigInteger two = new BigInteger("2");
if (b == BigInteger.ZERO)
return BigInteger.ONE;
BigInteger t = modExp (a, b.divide(two), n);
BigInteger c = (t.pow(2)).mod(n);
if (b.mod(two) == BigInteger.ONE)
c = (c.multiply(a)).mod(n);
return c;
}
The function with int:
public static int modexp(int a, int b, int n) {
if (b == 0) return 1;
long t = modexp(a, b/2, n); // use long for intermediate computations to eliminate overflow
long c = (t * t) % n;
if (b % 2 == 1)
c = (c * a) % n;
return (int) c;
}
The function is to calculate a^b mod p, For example:
a=4 b=6 p=11 result1 = 1 result2 = 4
a=9 b=2 p=11 result1 = 1 result2 = 4
a=5 b=6 p=23 result1 = 1 result2 = 8 ...
The obvious difference is the difference between int and BigInteger.
One difference is that int is a primitive type and BigInteger is a reference type. As such, it is better to use equals() when comparing BigIntegers. So b == BigInteger.ZERO should be BigInteger.ZERO.equals(b).
BigInteger is more suited to working with big numbers and will prevent you running into problems with overflowing the max int value, supported by Java.
Overflowing may be the cause you are getting a different result from the two functions as well. When this occurs, it doesn't cause any exception to be thrown, but the values of the ints get messed up.
In java int can count from -2^31 up to 2^31-1 because int are coded over 4 bytes but long can count from -2^63 up to 2^63-1 because long are coded over 8 bytes.
In the second method with this :
return (int) c;
you may loose data (the 4 first byte)
That could explain why your result are different because BigInteger are coded over much more byte than long

How to calculate power with no integer bigdecimal expoent?

Trying to calculate (a+b)^n where n is a real value in a BigDecimal variable, but BigDecimal.pow is designed for accept only integer values.
If the input is within the magnitude range supported by double, and you do not need more than 15 significant digits in the result, convert (a+b) and n to double, use Math.pow, and convert the result back to BigDecimal.
As long as you are just using an integer for the exponent, you can use a simple loop to calculate x^y:
public static BigDecimal pow(BigDecimal x, BigInteger y) {
if(y.compareTo(BigInteger.ZERO)==0) return BigDecimal.valueOf(1); //If the exponent is 0 then return 1 because x^0=1
BigDecimal out = x;
BigInteger i = BigInteger.valueOf(1);
while(i.compareTo(y.abs())<0) { //for(BigDecimal i = 1; i<y.abs(); i++) but in BigDecimal form
out = out.multiply(x);
i = i.add(BigInteger.ONE);
}
if(y.compareTo(BigInteger.ZERO)>0) {
return out;
} else if(y.compareTo(BigInteger.ZERO))<0) {
return BigDecimal.ONE.divide(out, MathContext.DECIMAL128); //Just so that it doesn't throw an error of non-terminating decimal expansion (ie. 1.333333333...)
} else return null; //In case something goes wrong
}
or for a BigDecimal x and y:
public static BigDecimal powD(BigDecimal x, BigDecimal y) {
return pow(x, y.toBigInteger());
}
Hope this helps!

Using BigIntegers as a condition in while loop in Java

I want to use a big integer value in my while loop condition but this is not working.
import java.util.Scanner;
import java.util.StringTokenizer;
public class NiceProbelm2 {
public static void main(String[]args){
Scanner input = new Scanner(System.in);
String number = input.nextLine();
StringTokenizer st = new StringTokenizer(number);
BigInteger base = null;
int power=0;
while (st.hasMoreTokens()) {
String token1 = st.nextToken();
String token2 = st.nextToken();
base = new BigInteger(token1);
power = Integer.parseInt(token2);
}
BigInteger result = base.pow(power);
//long fresult = (long)result;
BigInteger div = new BigInteger("10");
System.out.println(result);
BigInteger sum=null;
//NOt working while(result.compareTo(new BigInteger("0")) > 10 )
{
BigInteger digit = result.mod(div);
result = result.divide(div);
sum = sum.add(digit);
}
System.out.println(sum);
}
}
You should never compare the return value of compareTo() to anything other than 0. (BigInteger.compareTo() is a bit more specific, but the same rule still applies)
You can check if it's greater than 0, less than 0 or equal to 0. Only those 3 pieces of information are actually relevant. The actual value (if it returns 1 or 10 or 100) doesn't matter.
I think you problem with the previous solutions were you had a null pointer that was being thrown because your accumulator was not initialized. The following code produces the result you are looking for:
BigInteger result = base.pow(power);
BigInteger div = new BigInteger("10");
System.out.println(result);
//The following line is different, initialize the sum before using it.
BigInteger sum = BigInteger.ZERO;
while(!BigInteger.ZERO.equals(result)) {
BigInteger digit = result.mod(div);
result = result.divide(div);
sum = sum.add(digit);
}
System.out.println(sum);
I also wanted to point out that BigInteger has a method that provides both the quotient and remainder from a single division, which is more efficient than doing them both separately, and there is a "valueOf" method for BigInteger so you can use a numeric literal instead of a string:
BigInteger result = base.pow(power);
BigInteger div = BigInteger.valueOf(10);
System.out.println(result);
//Initialize the sum to zero
BigInteger sum = BigInteger.ZERO;
//While the result has a non-zero decimal digit
while(!BigInteger.ZERO.equals(result)) {
//this divides by ten (first element),
//and calculates the remainder (second element)
BigInteger[] lastDigit = result.divideAndRemainder(div);
result = lastDigit[0];
sum = sum.add(lastDigit[1]);
}
System.out.println(sum);
You have to use this condition:
result.compareTo(BigInteger.ZERO) > 0
It looks like you want to do while (result != 0) which you would write like
while (result.compareTo(BigInteger.ZERO) != 0)
Also, you need to initialize sum to BigInteger.ZERO.

Categories