Int to BigInteger, what's the difference? - java

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

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.

Unexpected output in Java while adding of two Integers [duplicate]

This question already has answers here:
How can I detect integer overflow on 32 bits int?
(5 answers)
Closed 2 years ago.
I am new in java language, here is m not able to understand, why program returning -2 after adding two full range integers.
class Variables {
public static void main(String[] args) {
int a = 2147483647;
int b = 2147483647;
long c = a + b;
System.out.println( c );
}
}
I am expacting 4294967294 value in my variable c, but why it returns -2
please explain me the reason behind this
You reach Integer.MAX_VALUE so you're going to -2147483648, then adding Integer.MAX_VALUE again will result in -2
To get 4294967294, you need to cast one value as long before to do a long sum and not an int one
int a = 2147483647;
System.out.println(a + 1); //-2147483648
int b = 2147483647;
System.out.println(a + b); // -2
long c = a + (long) b; // or ((long) a) + b;
System.out.println(c); //4294967294
The result of adding two ints is an int, which of course overflows when you add a and b. Only then is it promoted to a long.
You can get the result you expected by casting one of them to long before performing the addition:
long c = ((long) a) + b;

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

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);
}

Check integer is bit rotation of another integer

Given two integers a and b, how can we check that b is a rotated version of a?
For example if I have a = 0x01020304 (in binary 0000 0001 0000 0010 0000 0011 0000 0100), then the following b values are correct:
...
0x4080C1 (right-rotated by 2)
0x810182 (right-rotated by 1)
0x2040608 (left-rotated by 1)
0x4080C10 (left-rotated by 2)
...
For n bit numbers you can use KMP algorithm to search b inside two copies of a with complexity O(n).
In C++, without string conversion and assuming 32 bits int:
void test(unsigned a, unsigned b)
{
unsigned long long aa = a | ((unsigned long long)a<<32);
while(aa>=b)
{
if (unsigned(aa) == b) return true;
aa>>=1;
}
return false;
}
i think you have to do it in a loop (c++):
// rotate function
inline int rot(int x, int rot) {
return (x >> rot) | (x << sizeof(int)*8 - rot));
}
int a = 0x01020304;
int b = 0x4080C1;
bool result = false;
for( int i=0; i < sizeof(int)*8 && !result; i++) if(a == rot(b,i)) result = true;
In the general case (assuming arbitrary-length integers), the naive solution of consisting each rotation is O(n^2).
But what you're effectively doing is a correlation. And you can do a correlation in O(n log n) time by going via the frequency domain using an FFT.
This won't help much for length-32 integers though.
By deriving the answers here, the following method (written in C#, but shall be similar in Java) shall do the checking:
public static int checkBitRotation(int a, int b) {
string strA = Convert.ToString(a, 2).PadLeft(32, '0');
string strB = Convert.ToString(b, 2).PadLeft(32, '0');
return (strA + strA).IndexOf(strB);
}
If the return value is -1, b is not rotated version of a. Otherwise, b is rotated version of a.
If a or b is a constant (or loop-constant), you can precompute all rotations and sort them, and then do a binary search with the one that isn't a constant as key. That's fewer steps, but the steps are slower in practice (binary search is commonly implemented with a badly-predicted branch), so it might not be better.
In the case that it's really a constant, not a loop-constant, there are some more tricks:
if a is 0 or -1, it's trivial
if a has only 1 bit set, you can do the test like b != 0 && (b & (b - 1)) == 0
if a has 2 bits set, you can do the test like ror(b, tzcnt(b)) == ror(a, tzcnt(a))
if a has only one contiguous group of set bits, you can use
int x = ror(b, tzcnt(b));
int y = ror(x, tzcnt(~x));
const int a1 = ror(a, tzcnt(a)); // probably won't compile
const int a2 = ror(a1, tzcnt(~a1)); // but you get the idea
return y == a2;
if many rotations of a are the same, you may be able to use that to skip certain rotations instead of testing them all, for example if a == 0xAAAAAAAA, the test can be b == a || (b << 1) == a
you can compare to the smallest and biggest rotations of the constant for a quick pre-test, in addition to the popcnt test.
Of course, as I said in the beginning, none of this applies when a and b are both variables.
I would use Integer.rotateLeft or rotateRight func
static boolean isRotation(int a, int b) {
for(int i = 0; i < 32; i++) {
if (Integer.rotateLeft(a, i) == b) {
return true;
}
}
return false;
}

Port of Random generator from C to Java?

George Marsaglia has written an excellent random number generator that is extremely fast, simple, and has a much higher period than the Mersenne Twister. Here is the code with a description:
good C random number generator
I wanted to port the CMWC4096 code to Java, but it uses several unsigned datatypes so I am not sure how to do this properly. Here is the full C code:
/* choose random initial c<809430660 and */
/* 4096 random 32-bit integers for Q[] */
static unsigned long Q[4096],c=362436;
unsigned long CMWC4096(void) {
unsigned long long t, a=18782LL;
static unsigned long i=4095;
unsigned long x,r=0xfffffffe;
i = (i+1) & 4095;
t = a*Q[i] + c;
c = (t>>32);
x = t + c;
if (x < c) {
x++;
c++;
}
return (Q[i] = r - x);
}
Can anyone port this to Java? How does this work when you only have signed numbers available?
EDIT: Thanks everybody for the quick answers! For the first 100 million numbers this java code seems to produce the same result as the C code. It is 3 times faster than Java's java.util.Random.
public class ComplimentaryMultiplyWithCarryRandom {
/**
* Choose 4096 random 32-bit integers
*/
private long[] Q;
/**
* choose random initial c<809430660
*/
private long c = 362436;
private int i;
public ComplimentaryMultiplyWithCarryRandom() {
Random r = new Random(1);
Q = new long[4096];
// TODO initialize with real random 32bit values
for (int i = 0; i < 4096; ++i) {
long v = r.nextInt();
v -= Integer.MIN_VALUE;
Q[i] = v;
}
i = 4095;
}
int next() {
i = (i + 1) & 4095;
long t = 18782 * Q[i] + c;
c = t >>> 32;
long x = (t + c) & 0xffffffffL;
if (x < c) {
++x;
++c;
}
long v = 0xfffffffeL - x;
Q[i] = v;
return (int) v;
}
}
Most of the time there is no need to use larger numeric types for simulating unsigned types in Java.
For addition, subtraction, multiplication, shift left, the logical operations, equality
and casting to a smaller numeric type
it doesn't matter whether the operands are signed or unsigned,
the result will be the same regardless, viewed as a bit pattern.
For shifting to the right use >> for signed, >>> for unsigned.
For signed casting to a larger type just do it.
For unsigned casting from a smaller type to a long use & with a mask of type long for the smaller type.
E.g., short to long: s & 0xffffL.
For unsigned casting from a smaller type to an int use & with a mask of type int.
E.g., byte to int: b & 0xff.
Otherwise do like in the int case and apply a cast on top.
E.g., byte to short: (short) (b & 0xff).
For the comparison operators < etc. and division the easiest is to cast to a larger type and do the operation there.
But there also exist other options, e.g. do comparisons after adding an appropriate offset.
Can anyone port this to Java? How does
this work when you only have signed
numbers available?
No Stress! a=18782 so the largest t could ever be is not large enough to cause signed vs. unsigned problems. You would have to "upgrade" the result of using Q to a value equal to a 32-bit unsigned number before using it anywhere. e.g. if Q is an int (32-bit signed) then you'd have to do this before using it in the t=a*Q[i]+c statement, e.g.
t=a*(((long)Q[i])&0xffffffffL)+c
where this (((long)Q[i])&0xffffffffL) business promotes Q[i] to a 64-bit # and ensures its high 32 bits are 0's. (edit: NOTE: you need 0xffffffffL here. Java does the wrong thing if you use 0xffffffff, it seems like it "optimizes" itself to the wrong answer & you get a negative number if Q[i]'s high bit is 1.)
You should be able to verify this by running the algorithms in C++ and Java to compare the outputs.
edit: here's a shot at it. I tried running it in C++ and Java for N=100000; they both match. Apologies if I used bad Java idioms, I'm still fairly new to Java.
C++:
// marsaglia2003.cpp
#include <stdio.h>
#include <stdlib.h> // for atoi
class m2003
{
enum {c0=362436, sz=4096, mask=4095};
unsigned long Q[sz];
unsigned long c;
short i;
public:
m2003()
{
// a real program would seed this with a good random seed
// i'm just putting in something that makes the output interesting
for (int j = 0; j < sz; ++j)
Q[j] = j + (j << 16);
i = 4095;
c = c0;
}
unsigned long next()
{
unsigned long long t, a=18782LL;
unsigned long x;
unsigned long r=0xfffffffe;
i = (i+1)&mask;
t=a*Q[i]+c;
c=(unsigned long)(t>>32);
x=(unsigned long)t + c;
if (x<c)
{
x++;
c++;
}
return (Q[i]=r-x);
}
};
int main(int argc, char *argv[])
{
m2003 generator;
int n = 100;
if (argc > 1)
n = atoi(argv[1]);
for (int i = 0; i < n; ++i)
{
printf("%08x\n", generator.next());
}
return 0;
}
java: (slower than compiled C++ but it matches for N=100000)
// Marsaglia2003.java
import java.util.*;
class Marsaglia2003
{
final static private int sz=4096;
final static private int mask=4095;
final private int[] Q = new int[sz];
private int c=362436;
private int i=sz-1;
public Marsaglia2003()
{
// a real program would seed this with a good random seed
// i'm just putting in something that makes the output interesting
for (int j = 0; j < sz; ++j)
Q[j] = j + (j << 16);
}
public int next()
// note: returns a SIGNED 32-bit number.
// if you want to use as unsigned, cast to a (long),
// then AND it with 0xffffffffL
{
long t, a=18782;
int x;
int r=0xfffffffe;
i = (i+1)&mask;
long Qi = ((long)Q[i]) & 0xffffffffL; // treat as unsigned 32-bit
t=a*Qi+c;
c=(int)(t>>32);
// because "a" is relatively small this result is also small
x=((int)t) + c;
if (x<c && x>=0) // tweak to treat x as unsigned
{
x++;
c++;
}
return (Q[i]=r-x);
}
public static void main(String args[])
{
Marsaglia2003 m2003 = new Marsaglia2003();
int n = 100;
if (args.length > 0)
n = Integer.parseInt(args[0]);
for (int i = 0; i < n; ++i)
{
System.out.printf("%08x\n", m2003.next());
}
}
};
If you are implementing an RNG in Java, it is best to sub-class the java.util.Random class and over-ride the protected next(int) method (your RNG is then a drop-in replacement for java.util.Random). The next(int) method is concerned with randomly-generated bits, not what vales those bits might represent. The other (public) methods of java.util.Random use these bits to construct random values of different types.
To get around Java's lack of unsigned types you usually store numbers in a bigger variable type (so shorts get upgraded to ints, ints to long). Since you're using long variables here, you're going to have to step up to BigInteger, which will probably wreck any speed gains that you're getting out of the algorithm.
You can use signed numbers provided the values don't overflow...for example long in java is a 64 bit signed integer. However the intent in this algorithm seems to be to use a 64 bit unsigned value, and if so I think you would be out of luck with the basic types.
You could use the multiprecision integers provided in the java class libraries (BigInteger). Or you could implement your own 64 bit unsigned type as an Object containing two java longs to represent the least significant and most significant words (but you'd have to implement the basic arithmetic operations yourself in the class).
Note: In your C code, I inferred that long is 32 bits wide, and long long is 64 bits wide.
Here is my way of porting that code to Java with the minimum number of changes:
/* choose random initial 0<=c<809430660 and */
/* 4096 random 32-bit integers for Q[] */
int[] Q = new int[4096];
int c = 362436;
int i = 4095;
int CMWC4096() {
long a = 18782;
int r = 0xfffffffe;
i = (i + 1) & 4095;
long t = a * Q[i] + c;
c = (int)(t >>> 32);
int x = (int)(t + c);
if (0 <= x && x < c) {
x++;
c++;
}
return (Q[i] = r - x);
}

Categories