Hi I have an algorithm in which I need to apply operations to BigInt's.
I understand that BigInt's can be manipulated using the Maths class such as:
import java.math.*;
BigInteger a;
BigInteger b = BigInteger.ZERO;
BigInteger c = BigInteger.ONE;
BigInteger d = new BigInteger ("3");
BigInteger e = BigInteger.valueOf(5);
a.multiply(b);
a.add(b);
a.substract(b);
a.divide(b);
I need to be able to apply greater than for a while condition e.g.
while (a > 0) {
Which gives me a syntax error saying "bad operand types for binary operator '>', first type: java.math.BigInteger, second type: int.
I also need to be able to apply the modulo (%) operator to a BigInteger.
b = a % c;
Can anyone suggest a way of doing this?
If there isn't a solution then I'm just going to have to somehow manipulate my BigInteger into an unique Long using a reduce function (which is far from ideal).
Silverzx.
To compare BigInteger, use BigInteger.compareTo.
while(a.compareTo(BigInteger.ZERO) > 0)
//...
And for modulo (%), use BigInteger.mod.
BigInteger blah = a.mod(b);
For comparing BigIntegers you may use compareTo, but in the special case when you compare to 0 the signum method will also do the job(and may be a bit faster). As for taking the remainder of a given division you may use the method mod(better option here) or alternatively use divideAndRemainder which returns an array with both the result of the division and the remainder.
Related
import java.lang.Math;
import java.math.BigInteger;
import java.math.BigDecimal;
public class Main {
public static void main(String[] args) {
int e1 = 20, d = 13;
BigInteger C = BigDecimal.valueOf(e1).toBigInteger();
BigInteger po = C.pow(d);
System.out.println("pow is:" + po);
int num = 11;
BigInteger x = po;
BigInteger n = BigDecimal.valueOf(num).toBigInteger();
BigInteger p, q, m;
System.out.println("x: " + x);
q=(x / n);
p=(q * n);
m=(x - p);
System.out.println("mod is:" + m);
}
}
I've tried looking for some answers related to it but unable to solve. Please can someone tell me what's wrong in this. I changed the datatype to integer but then the power function doesn't works.
this is the error which I get:
error: bad operand types for binary operator '/'
q=(x/n);
^
first type: BigInteger
second type: BigInteger
Main.java:33: error: bad operand types for binary operator '*'
p=(q*n);
^
first type: BigInteger
second type: BigInteger
Main.java:34: error: bad operand types for binary operator '-'
m=(x-p);
^
first type: BigInteger
second type: BigInteger
3 errors
.
Explanation
You can not use the operators on BigInteger. They are not primitives like int, they are classes. Java has no operator overloading.
Take a look at the class documentation and use the corresponding methods:
BigInteger first = BigInteger.ONE;
BigInteger second = BigInteger.TEN;
BigInteger addResult = first.add(second);
BigInteger subResult = first.subtract(second);
BigInteger multResult = first.multiply(second);
BigInteger divResult = first.divide(second);
Operator Details
You can look up the detailed definitions for the operators and when you can use them in the Java Language Specification (JLS).
Here are some links to the relevant sections:
Multiplication * §15.17.1
Division / §15.17.2
String concatenation + §15.18.1
Addition and subtraction + - §15.18.2
Most of them work with the notion of Numeric Type §4, which consists of Integral Type and FloatingPointType:
The integral types are byte, short, int, and long, whose values are 8-bit, 16-bit, 32-bit and 64-bit signed two's-complement integers, respectively, and char, whose values are 16-bit unsigned integers representing UTF-16 code units (§3.1).
The floating-point types are float, whose values include the 32-bit IEEE 754 floating-point numbers, and double, whose values include the 64-bit IEEE 754 floating-point numbers.
Additionally, Java can unbox wrapper classes like Integer into int and vice versa, if needed. That adds the unboxing conversions §5.1.8 to the set of supported operands.
Notes
Your creation of BigInteger is unnecessarily long and complicated:
// Yours
BigInteger C = BigDecimal.valueOf(e1).toBigInteger();
// Prefer this instead
BigInteger c = BigInteger.valueOf(e1);
And if possible, you should prefer to go from String to BigInteger and from BigInteger to String. Since the purpose of BigInteger is to use it for numbers that are too big to be represented with the primitives:
// String -> BigInteger
String numberText = "10000000000000000000000000000000";
BigInteger number = new BigInteger(numberText);
// BigInteger -> String
BigInteger number = ...
String numberText = number.toString();
Also, please stick to Java naming conventions. Variable names should be camelCase, so c and not C.
Additionally, prefer to have meaningful variable names. A name like c or d does not help anyone to understand what the variable is supposed to represent.
Arithmetic operations are not working on Objects in Java. However there are already methods to do so like BigInteger#add, BigInteger#divide etc. in BigInteger. Instead of doing
q=(x/n)
you would do
q = x.divide(n);
You can't do operands such as "*","/","+" on objects in Java, if you want these operations you need to do it like this
q = x.divide(n);
p=q.multiply(n);
m=x.subtract(p);
Is there any ready-made Java library for operations over BigInteger and BigDecimal objects?
I'd like to use square root and ++ operators.
Thank you
P.S. BigInteger.add() should be used instead of ++, I got it.
What about square root from BigInteger?
BigInteger is immutable. That makes something like the ++-operator on it conceptually impossible. You can not change the value of a given BigInteger, just like you can't do it with String.
Incrementing
You always have to create a new BigInteger that holds the incremented value (you can then of course store the reference to that BigInteger in the same variable).
Edit: As pointed out in the comment, "incrementing" would look like:
BigInteger result = a.add(BigInteger.ONE);
or
a = a.add(BigInteger.ONE);
Note that both lines do not change the value of the BigInteger which a originally points to. The last line creates a new BigInteger and stores the reference to it in a.
Calculating the Square
You can calculate the square of a BigInteger like this:
BigInteger a = BigInteger.valueOf(2);
BigInteger a_square = a.multiply(a); // a^2 == a * a
or
BigInteger a_square = a.pow(2);
Square Root
The code is taken from https://gist.github.com/JochemKuijpers/cd1ad9ec23d6d90959c549de5892d6cb .
It uses simple bisection and a clever upper bound. Note that a.shiftRight(x) is equivalent to a / 2^x (only for non-negative numbers, but that is all we deal with, anyway)
BigInteger sqrt(BigInteger n) {
BigInteger a = BigInteger.ONE;
BigInteger b = n.shiftRight(5).add(BigInteger.valueOf(8));
while (b.compareTo(a) >= 0) {
BigInteger mid = a.add(b).shiftRight(1);
if (mid.multiply(mid).compareTo(n) > 0) {
b = mid.subtract(BigInteger.ONE);
} else {
a = mid.add(BigInteger.ONE);
}
}
return a.subtract(BigInteger.ONE);
}
Using Operators Instead of Methods
Operator overloading like in C++ is not possible in Java.
(EDIT: Before more people downvote, I did look at the Javadoc beforehand but since I'm a beginner I wasn't sure where in the document to look. See my response to Jim G, which is posted below. I understand that this question is maybe viewed as too basic. But I think it has some value for other beginners in my situation. So please, consider the full situation from a beginner's perspective before downvoting.)
I want to divide a BigInteger by a regular integer (i.e. int) but I don't know how to do this. I did a quick search on Google and on Stack Exchange but didn't find any answers.
So, how can I divide a BigInteger by an int? And while we're at it, how can I add/subtract BigInts to ints, compare BigInts to ints, et cetera?
Just use BigInteger.valueOf(long) factory method. An int can be implicitly "widened" to be long... This is always the case when going from smaller to large, e.g. byte => short, short => int, int => long.
BigInteger bigInt = BigInteger.valueOf(12);
int regularInt = 6;
BigInteger result = bigInt.divide(BigInteger.valueOf(regularInt));
System.out.println(result); // => 2
Convert the Integer to BigInteger and than divide both BigInteger, as following:
BigInteger b = BigInteger.valueOf(10);
int x = 6;
//convert the integer to BigInteger.
BigInteger converted = new BigInteger(Integer.toString(x));
//now you can divide, add, subtract etc.
BigInteger result = b.divide(converted); //but this will give you Integer values.
System.out.println(result);
result = b.add(converted);
System.out.println(result);
Above division will give you Integer values of divisions, to get exact values, use BigDecimal.
EDIT:
To remove two intermediate variables converted and result in above code:
BigInteger b = BigInteger.valueOf(10);
int x = 6;
System.out.println(b.divide(new BigInteger(Integer.toString(x))));
OR
Scanner in = new Scanner(System.in);
System.out.println(BigInteger.valueOf((in.nextInt())).divide(new BigInteger(Integer.toString(in.nextInt()))));
I try using BigInteger like this (where m and n are integers):
m.substract(BigInteger.ONE), n.substract(BigInteger.ONE)
it says: "cannot invoke subtract(BigInteger) on the primitive type int"
What am I doing wrong here?
int is a native datatype, it is not an object!!!
Maybe you should declare m and n as BigIntegers instead?
m.substract(BigInteger.ONE) here m is only an int it is neither a BigInteger nor an Object of any kind, but a primitive. If you want to call a method (substract(BigInteger i)) then m and n need to be an Object of some class that actually has the method substract(BigInteger i).
You could do it like this:
BigInteger mBig = new BigInteger(m); // in this case n is a String
mBig = mBig.subtract(BigInteger.ONE);
BTW: it is called subtract and not substract (without the s)
ints are primitive times, they do not have methods.
The boxed type, Integer doesn't have a subract(BigInteger) method either.
You need to either make the ints into BigIntegers with BigInteger.valueOf or make the BigIntegers into ints with intValue.
The latter approach is unsafe as the BigInteger may be bigger than Integer.MAX_VALUE.
So you need to do
BigInteger.valueOf(m).subtract(BigInteger.ONE),
BigInteger.valueOf(n).subtract(BigInteger.ONE)
But this is a little messy so why not do
BigInteger.valueOf(m - 1), BigInteger.valueOf(n - 1)
I'm playing with numbers in Java, and want to see how big a number I can make. It is my understanding that BigInteger can hold a number of infinite size, so long as my computer has enough Memory to hold such a number, correct?
My problem is that BigInteger.pow accepts only an int, not another BigInteger, which means I can only use a number up to 2,147,483,647 as the exponent. Is it possible to use the BigInteger class as such?
BigInteger.pow(BigInteger)
Thanks.
You can write your own, using repeated squaring:
BigInteger pow(BigInteger base, BigInteger exponent) {
BigInteger result = BigInteger.ONE;
while (exponent.signum() > 0) {
if (exponent.testBit(0)) result = result.multiply(base);
base = base.multiply(base);
exponent = exponent.shiftRight(1);
}
return result;
}
might not work for negative bases or exponents.
You can only do this in Java by modular arithmetic, meaning you can do a a^b mod c, where a,b,c are BigInteger numbers.
This is done using:
BigInteger modPow(BigInteger exponent, BigInteger m)
Read the BigInteger.modPow documentation here.
The underlying implementation of BigInteger is limited to (2^31-1) * 32-bit values. which is almost 2^36 bits. You will need 8 GB of memory to store it and many times this to perform any operation on it like toString().
BTW: You will never be able to read such a number. If you tried to print it out it would take a life time to read it.
Please be sure to read the previous answers and comments and understand why this should not be attempted on a production level application. The following is a working solution that can be used for testing purposes only:
Exponent greater than or equal to 0
BigInteger pow(BigInteger base, BigInteger exponent) {
BigInteger result = BigInteger.ONE;
for (BigInteger i = BigInteger.ZERO; i.compareTo(exponent) != 0; i = i.add(BigInteger.ONE)) {
result = result.multiply(base);
}
return result;
}
This will work for both positive and negative bases. You might want to handle 0 to the power of 0 according to your needs, since that's technically undefined.
Exponent can be both positive or negative
BigDecimal allIntegersPow(BigInteger base, BigInteger exponent) {
if (BigInteger.ZERO.compareTo(exponent) > 0) {
return BigDecimal.ONE.divide(new BigDecimal(pow(base, exponent.negate())), 2, RoundingMode.HALF_UP);
}
return new BigDecimal(pow(base, exponent));
}
This re-uses the first method to return a BigDecimal with 2 decimal places, you can define the scale and rounding mode as per your needs.
Again, you should not do this in a real-life, production-level system.
java wont let you do BigInteger.Pow(BigInteger) but you can just put it to the max integer in a loop and see where a ArithmeticException is thrown or some other error due to running out of memory.
2^2,147,483,647 has at least 500000000 digit, in fact computing pow is NPC problem, [Pow is NPC in the length of input, 2 input (m,n) which they can be coded in O(logm + logn) and can take upto nlog(m) (at last the answer takes n log(m) space) which is not polynomial relation between input and computation size], there are some simple problems which are not easy in fact for example sqrt(2) is some kind of them, you can't specify true precision (all precisions), i.e BigDecimal says can compute all precisions but it can't (in fact) because no one solved this up to now.
I can suggest you make use of
BigInteger modPow(BigInteger exponent, BigInteger m)
Suppose you have BigInteger X, and BigInteger Y and you want to calculate BigInteger Z = X^Y.
Get a large Prime P >>>> X^Y and do Z = X.modPow(Y,P);
For anyone who stumbles upon this from the Groovy side of things, it is totally possible to pass a BigInteger to BigInteger.pow().
groovy> def a = 3G.pow(10G)
groovy> println a
groovy> println a.class
59049
class java.math.BigInteger
http://docs.groovy-lang.org/2.4.3/html/groovy-jdk/java/math/BigInteger.html#power%28java.math.BigInteger%29
Just use .intValue()
If your BigInteger is named BigValue2, then it would be BigValue2.intValue()
So to answer your question, it's
BigValue1.pow(BigValue2.intValue())