I had the task to implement RSA algorithm, I read about it in Cormen's book and got most of information from there. I thought it worked good until I faced large p and q primes. For numbers about 250 and lower encryption and decryption works good, however if they are larger, modular exponentation returns negative numbers, which doesn't make sense.
I know that encrypted number can't be larger than n. I read that I can also compute inverse modulo by using extended GCD algorithm and taking x as that value, but when I tried calling extendedEuclid(phi, e)[1] it returned different values than function in RSA class. How can I fix it ?
Here is code for all needed components to compute keys.
Euclid Algorithm
public class Euclid {
public static int euclid(int a, int b) {
if (a < b) {
int tmp = a;
a = b;
b = tmp;
}
if (b == 0) {
return a;
} else {
return euclid(b, a % b);
}
}
public static int[] extendedEuclid(int a, int b) {
if (a < b) {
int tmp = a;
a = b;
b = tmp;
}
if (b == 0) {
return new int[]{a, 1, 0};
} else {
int vals[] = extendedEuclid(b, a % b);
int d = vals[0];
int x = vals[2];
int y = vals[1] - (int) Math.floor(a / b) * vals[2];
return new int[]{d, x, y};
}
}
}
Modular Exponentation
public class Modular {
public static int modularExponentation(int a, int b, int n) {
int c = 0;
int d = 1;
String binaryString = Integer.toBinaryString(b);
for (int i = 0; i < binaryString.length(); i++) {
c = 2 * c;
d = (d * d) % n;
if (binaryString.charAt(i) == '1') {
c = c + 1;
d = (d * a) % n;
}
}
return d;
}
}
RSA generator
public class RsaKeyGenerator {
int d;
int e;
int n;
public RsaKeyGenerator() {
int p = 827;
int q = 907;
n = p * q;
int phi = (p - 1) * (q - 1);
e = computeCoPrime(phi);
d = invMod(e, phi);
System.out.println("Public: " + e);
System.out.println("Private: " + d);
}
private static int computeCoPrime(int phi) {
int e = 2;
while (Euclid.euclid(e, phi) != 1) {
e++;
}
return e;
}
private int invMod(int a, int n) {
int a0, n0, p0, p1, q, r, t;
p0 = 0;
p1 = 1;
a0 = a;
n0 = n;
q = n0 / a0;
r = n0 % a0;
while (r > 0) {
t = p0 - q * p1;
if (t >= 0) {
t = t % n;
} else {
t = n - ((-t) % n);
}
p0 = p1;
p1 = t;
n0 = a0;
a0 = r;
q = n0 / a0;
r = n0 % a0;
}
return p1;
}
public int encrypt(int num) {
return Modular.modularExponentation(num, e, n);
}
public int decrypt(int cipher) {
return Modular.modularExponentation(cipher, d, n);
}
public static void main(String[] args) {
RsaKeyGenerator rsa = new RsaKeyGenerator();
int cip = rsa.encrypt(1343);
System.out.println(cip);
System.out.println(rsa.decrypt(cip));
}
}
The problem you're facing is integer overflow so if you're trying to store a number higher than 2^31 -1 in a signed integer which just isn't possible. So what ends up happening when you hit that limit is that the number wraps around to -2^31 -1.
What you want to do is look into the BigInteger class which will let you store much bigger numbers and should work fine.
The integer overflow happens at this line in the ModularExponentiation class:
d = (d * a) % n;
Related
My task is to determine whether the sum of numbers in the Fibonacci series from A to B is divisible by the number D.
I use the fast doubling algorithm to find the required number in the series, and use the formula: Fa + ... + Fb = Fb+2 - 1 - (Fa+1 - 1) - to determine the sum of the series, but this is not enough. For testing, I took a series from A = 10,000,000 to B = 20,000,000, the number D = 987654, the program was executed in 3.3 seconds, this is a lot. Are there ways to optimize my code?
class Solution {
private static Map<BigDecimal, BigDecimal> previousValuesHolder;
static {
previousValuesHolder = new HashMap<>();
previousValuesHolder.put(BigDecimal.ZERO, BigDecimal.ZERO);
previousValuesHolder.put(BigDecimal.ONE, BigDecimal.ONE);
}
private static BigInteger totalSum;
public static void main(String args[]) {
Scanner in = new Scanner(System.in);
int nb = in.nextInt();
for (int i = 0; i < nb; i++) {
int a = in.nextInt();
int b = in.nextInt();
int d = in.nextInt();
totalSum = calculateTotalSum(a, b);
System.out.println(checkSum(totalSum, a, b, d));
}
}
private static BigInteger calculateTotalSum(int start, int finish) {
BigInteger res1 = fibDoubleFast(finish + 2).subtract(BigInteger.valueOf(1));
BigInteger res2 = fibDoubleFast(start + 1).subtract(BigInteger.valueOf(1));
return res1.subtract(res2);
}
private static String checkSum(BigInteger sum, int start, int finish, int d) {
BigInteger result = sum.remainder(BigInteger.valueOf(d));
return result.longValue() > 0
? String.format("F_%s + ... + F_%s is NOT divisible by %s", start, finish, d)
: String.format("F_%s + ... + F_%s is divisible by %s", start, finish, d);
}
private static BigInteger fibDoubleFast(int n) {
BigInteger a = BigInteger.ZERO;
BigInteger b = BigInteger.ONE;
int m = 0;
for (int bit = Integer.highestOneBit(n); bit != 0; bit >>>= 1) {
BigInteger d = multiply(a, b.shiftLeft(1).subtract(a));
BigInteger e = multiply(a, a).add(multiply(b, b));
a = d;
b = e;
m *= 2;
if ((n & bit) != 0) {
BigInteger c = a.add(b);
a = b;
b = c;
m++;
}
}
return a;
}
private static BigInteger multiply(BigInteger x, BigInteger y) {
return x.multiply(y);
}
}
For small values of D (less than 2^31, I think) , you could do the whole code using long, and do mod D for every intermediate result.
private static long fibDoubleFastModD(int n, long m) {
...
long d = (...) % m;
long e = (...) % m;
...
}
I'm writing a divide and conquer algorithm but I'm having trouble recursively calling it. It says it cannot find the symbol method Multiply and the variables m, e, m
public class Multiply {
private static int randomInt(int size) {
int maxval = (1 << size) - 1;
return (int)(Math.random()*maxval);
}
public static int[] naive(int size, int x, int y) {
int[] result = new int[3];
if (size == 1) {
result[0] = x*y;
}
else {
int m = size/2;
int a = x/2;
int b = x % (int)Math.pow(2,m);
int c = y / (int)Math.pow(2,m);
int d = y % (int)Math.pow(2,m);
int e = Multiply(a,c,m);
int f = Multiply(b,d,m);
int g = Multiply(b,c,m);
int h = Multiply(a,d,m);
}
return ((int)Math.pow(2,2*m)*e) + ((int)Math.pow(2,m)*(g+h)) + f;
}
Try Multiply.naive(x,y,z) instead of Multiply(x,y,z)
This is a code in an online contest I've been trying. The time limit set at the online judge is 1 sec and the order of test cases is 10^5.
import java.util.Scanner;
class My_Number {
int primeNo;
boolean divisible[] = new boolean [60];
My_Number(int primeNo) {
this.primeNo = primeNo;
}
void setDivisible() {
for (int i=0; i<60; i++) {
if(i%primeNo == 0) {
divisible[i] = true;
}
}
}
}
class BestWorse {
My_Number gb [] = {
new My_Number(2), new My_Number(3), new My_Number(5), new My_Number(7), new My_Number(11),
new My_Number(13), new My_Number(17), new My_Number(19), new My_Number(23), new My_Number(29),
new My_Number(31), new My_Number(37), new My_Number(41), new My_Number(43), new My_Number(47),
new My_Number(53), new My_Number(59)
};
boolean master_list [] = new boolean [86400];
void initialize() {
for (My_Number gb1 : gb) {
gb1.setDivisible();
}
}
private boolean isBad(int hh, int mm, int ss) {
for(My_Number gb1: gb) {
if(gb1.divisible[hh] && gb1.divisible[mm] && gb1.divisible[ss]) {
return true;
}
}
return false;
}
private int findGCD(int a, int b) {
int r, i;
while(b!=0){
r = a % b;
a = b;
b = r;
}
return a;
}
void fillUpTheMasterList() {
int hh =0, mm = 0, ss = 1;
while( !(hh==0 && ss==0 && mm==0)) {
if (isBad(hh, mm, ss)) {
master_list[hh*60*60+mm*60+ss] = true;
}
ss++;
if(ss == 60) {
ss = 0;
mm++;
if(mm == 60) {
mm = 0;
hh++;
if(hh == 24) {
hh = 0;
}
}
}
}
}
String countBestAndWorse(int hh, int mm, int ss) {
int good = 0, bad = 0;
for(int i=hh*60*60+mm*60+ss; i<86400; i++) {
if(master_list[i]) {
bad++;
}
else {
good++;
}
}
if(good != 0 && bad != 0)
{
int gcd = findGCD(good, bad);
good /= gcd;
bad /= gcd;
}
return bad + ":" +good;
}
public static void main(String[]args) {
int n;
Scanner scn = new Scanner(System.in);
BestWorse best_worse = new BestWorse();
best_worse.initialize();
best_worse.fillUpTheMasterList();
n = scn.nextInt();
for(int i=0; i<n;i++) {
int hh = scn.nextInt();
int mm = scn.nextInt();
int ss = scn.nextInt();
System.out.println(best_worse.countBestAndWorse(hh, mm, ss));
}
}
}
For some reason, I am continuously getting the error as 'Time limit exceeded'.
Things I tried:
Using BufferedReader instead of Scanner
Maintaining a master_list of the answer(already implemented in my solution).
I tried the Netbeans profiler and it's output for input of 5000 (hh=0 mm=0 ss=1) numbers is pasted here. Also, the question is posted here.
From the profiler, it seems like findGCD is taking up majority of the time. But I googled around and found out that this is indeed the fastest algorithm to calculate GCD. I also tried to maintain a lookup table for GCD; perhaps the same GCD is calculated again and again. Still no luck!
I've reached my limit for this question and need help. Can anyone please help me out here?
Its all about using the correct algorithm.
Check out this approach:
import java.util.Scanner;
public class GoodBadTime
{
private int goodTimeCounter[][][];
private int badTimeCounter[][][];
private static final int primes[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23 };
public GoodBadTime ()
{
initializeGoodBadTimes ();
try (Scanner scanner = new Scanner (System.in))
{
int testCases = scanner.nextInt ();
for (int i = 0; i < testCases; ++i)
{
int h = scanner.nextInt ();
int m = scanner.nextInt ();
int s = scanner.nextInt ();
System.out.println (badTimeCounter[h][m][s] + ":" + goodTimeCounter[h][m][s]);
}
}
}
private void initializeGoodBadTimes ()
{
goodTimeCounter = new int[24][60][60];
badTimeCounter = new int[24][60][60];
int cumulativeGoodCounter = 0;
int cumulativeBadCounter = 0;
for (int h = 23; h >= 0; --h)
{
for (int m = 59; m >= 0; --m)
{
for (int s = 59; s >= 0; --s)
{
boolean isBadTime = false;
int prime;
for (int p = 0; p < primes.length && ((prime = primes[p]) <= h); ++p)
{
if (h % prime == 0 && m % prime == 0 && s % prime == 0)
{
isBadTime = true;
break;
}
}
if (isBadTime)
{
++cumulativeBadCounter;
}
else
{
++cumulativeGoodCounter;
}
int gcd = GCD (cumulativeGoodCounter, cumulativeBadCounter);
goodTimeCounter[h][m][s] = cumulativeGoodCounter / gcd;
badTimeCounter[h][m][s] = cumulativeBadCounter / gcd;
}
}
}
}
private int GCD (int p, int q)
{
if (p == 0 || q == 0)
{
return 1;
}
while (q != 0)
{
int temp = q;
q = p % q;
p = temp;
}
return p;
}
public static void main (String[] args)
{
new GoodBadTime ();
}
}
Let me know if there's something I need to explain in my code that isn't obvious, so that I can edit my answer and explain it to you.
This was just my first attempt to solve it, there can be better ways to do it as well.
But this approach should give out the output within 1 second, so I guess, I don't cross the threshold limit with this approach.
Update
Here's an update to the answer:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class GoodBadTime
{
private int goodTimeCounter[];
private int badTimeCounter[];
private static final int primes[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23 };
public GoodBadTime ()
{
initializeGoodBadTimes ();
try (BufferedReader reader = new BufferedReader (new InputStreamReader (System.in)))
{
int testCases = Integer.parseInt (reader.readLine ());
for (int i = testCases; i > 0; --i)
{
String[] hms = reader.readLine ().split ("\\s+");
int h = Integer.parseInt (hms[0]);
int m = Integer.parseInt (hms[1]);
int s = Integer.parseInt (hms[2]);
int index = h + 24 * (m + 60 * s);
System.out.printf ("%d:%d\n", badTimeCounter[index], goodTimeCounter[index]);
}
}
catch (IOException e)
{
e.printStackTrace ();
}
}
private void initializeGoodBadTimes ()
{
goodTimeCounter = new int[24 * 60 * 60];
badTimeCounter = new int[24 * 60 * 60];
int cumulativeGoodCounter = 0;
int cumulativeBadCounter = 0;
for (int h = 23; h >= 0; --h)
{
for (int m = 59; m >= 0; --m)
{
for (int s = 59; s >= 0; --s)
{
boolean isBadTime = false;
int prime;
for (int p = 0; p < primes.length && ((prime = primes[p]) <= h); ++p)
{
if (h % prime == 0 && m % prime == 0 && s % prime == 0)
{
isBadTime = true;
++cumulativeBadCounter;
break;
}
}
if (!isBadTime)
{
++cumulativeGoodCounter;
}
int gcd = GCD (cumulativeGoodCounter, cumulativeBadCounter);
// Original[h, m, s] = Flat[h + 24 * (m + 60 * s)]
int index = h + 24 * (m + 60 * s);
goodTimeCounter[index] = cumulativeGoodCounter / gcd;
badTimeCounter[index] = cumulativeBadCounter / gcd;
}
}
}
}
private int GCD (int p, int q)
{
if (p == 0 || q == 0)
{
return 1;
}
while (q != 0)
{
int temp = q;
q = p % q;
p = temp;
}
return p;
}
public static void main (String[] args)
{
new GoodBadTime ();
}
}
This should be faster than the previous one, since I'm using 1D array and BufferedReader this time.
Here's a C equivalent:
#include <stdio.h>
int goodTimeCounter[24 * 60 * 60];
int badTimeCounter[24 * 60 * 60];
const int primes[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23 };
int GCD (int p, int q)
{
if (p == 0 || q == 0)
{
return 1;
}
while (q != 0)
{
int temp = q;
q = p % q;
p = temp;
}
return p;
}
void initializeGoodBadTimes ()
{
int cumulativeGoodCounter = 0;
int cumulativeBadCounter = 0;
for (int h = 23; h >= 0; --h)
{
for (int m = 59; m >= 0; --m)
{
for (int s = 59; s >= 0; --s)
{
int isBadTime = 0;
int prime;
for (int p = 0; p < 9 && ((prime = primes[p]) <= h); ++p)
{
if (h % prime == 0 && m % prime == 0 && s % prime == 0)
{
isBadTime = 1;
++cumulativeBadCounter;
break;
}
}
if (!isBadTime)
{
++cumulativeGoodCounter;
}
int gcd = GCD (cumulativeGoodCounter, cumulativeBadCounter);
// Original[h, m, s] = Flat[h + 24 * (m + 60 * s)]
int index = h + 24 * (m + 60 * s);
goodTimeCounter[index] = cumulativeGoodCounter / gcd;
badTimeCounter[index] = cumulativeBadCounter / gcd;
}
}
}
}
int main (int argc, const char * argv[])
{
initializeGoodBadTimes();
int testCases;
scanf("%d", &testCases);
for(int i = testCases; i > 0; --i)
{
int h, m, s;
scanf("%d %d %d", &h, &m, &s);
int index = h + 24 * (m + 60 * s);
printf("%d:%d\n", badTimeCounter[index], goodTimeCounter[index]);
}
return 0;
}
Note: GCD is calculated constant number of times, irrespective of the input size.
Also, int is sufficient for this program, since no counter ever exceeds 86400 since that's the maximum number of good or bad times that can happen.
Its equally strange for me that Online Judge is calling it as "Wrong Answer", since I think I am following every constraint set by the question.
Also, while testing for the two inputs, the program gave the correct answer despite the input being far apart in time. Induction would say that it should keep giving correct answers. Do you happen to know which output is wrong?
Also, can you put a link to this question which is present on the Online Judge site, so that I can check it out myself, and provide a correct answer to you?
The contest is rather unclear; at least to me. It says "none of them was divisible by the same prime number" which makes no sense, and if it did, I'd interpret it as that all the numbers must be co-prime. The next sentence sounds more like gcd(h, gcd(m, s)) <= 1 for good days.
I'm offering some untested potential improvements to Aman Agnihotri's algorithms. By creating the cumulative table, the biggest optimization is already done.
There is a faster GDC algorithm, but I wouldn't bother as all you need is to fill a 60x60 table. This could be done even without GCD by something like
int[] gcdTable = new int[60*60];
Arrays.fill(gcdTable, 1);
for (int p=2; p<60; ++p)
for (int i=0; i<60; i+=p)
for (int j=0; j<60; j+=p)
gcdTable[60*i+j] = Math.max(gcdTable[60*i+j], p);
Then use it as
int gcd(int a, int b) {
return gcdTable[60*a+b];
}
in
boolean isGood(int h, int m, int s) {
return gcd(h, gcd(m, s)) <= 1;
}
to fill the cumulative table. I guess, using a 1D array via
int secondOfDay(int h, int m, int s) {
return 3600*h + 60*m + s;
}
should be a bit faster than a 3D array. You don't need to store both remaining good and bad seconds, as their sum equals to 24*3600 - secondOfDay. My above table is too small for use for the expressing of the B:G ratio in smallest common terms, so you'll need one proper GCD per sample.
How to deal with a big hashcode value in rolling hash Rabin-Karp algorithm ? I use modular arithmetic to avoid negative number, however there is a problem when the hashcode exceeds my modulo number (N = 83559671). I set my base number to be prime (the number to calculate hashcode) as well as the modulo number (really big), but it doesn't work with long string. Can anyone see the problem?
Here is my code.
public static void main(String [] args){
int P = 13; // base
long M = 83559671;
long iHash = 0;
String word = "abcbadccaaaabbbb";
int WINDOW = 9;
for(int i = 0; i < WINDOW; i++){
iHash = int_mod(int_mod(iHash*P, M) + word[i], M);
}
for(int i = WINDOW; i < word.length; i++){
iHash = int_mod(iHash - word[i-WINDOW] * get_pow(P, WINDOW-1, M), M);
iHash = int_mod(iHash * P, M);
iHash = int_mod(iHash + word[i], M);
}
}
public static long get_pow(int p, int t, long M){
long a = 1;
for(int i = 0 ; i < t; i++){
a = int_mod(a * p, M);
}
return a;
}
public static long int_mod(long a, long b){
return (a % b+ b) % b;
}
The problem is when I have any string's length longer than 8 then the hashcode of the string exceeds the modulo number 83559671, and that leads to a wrong answer when I make a comparison. Any shorter strings work properly.
You don't need to do the modulus at all. Here's a demo:
public class Foo {
private static int hash(String s) {
int hash = 0;
for (int i = 0; i < s.length(); i++) {
hash *= 31;
hash += s.charAt(i);
}
return hash;
}
public static void main(String[] args) {
String s1 = "abcdefghij";
String s2 = s1.substring(1) + "k";
int pow = 1;
for (int i = 0; i < s1.length(); i++) {
pow *= 31;
}
System.out.printf("hash(%s) = %d%n", s1, hash(s1));
System.out.printf("hash(%s) = %d%n31 * hash(%s) - (31^%d * %s) + %s = %s%n",
s2,
hash(s2),
s1,
s1.length(),
s1.charAt(0),
s2.charAt(s2.length() - 1),
31 * hash(s1) - (pow * s1.charAt(0)) + s2.charAt(s2.length() - 1));
}
}
This (correctly) prints out:
hash(abcdefghij) = -634317659
hash(bcdefghijk) = 21611845
31 * hash(abcdefghij) - (31^10 * a) + k = 21611845
Why don't you treat your string as a polynomial? Suppose you have a string S of length n. Now take a look at the following function: F(x) = S[0]*x^(n-1) + S[1]*x^(n-2) + ... + S[i]*x^(n-i-1) + ... + S[n - 2]*x + S[n-1]. What happens if you try to compute F(P), where P is a base from your code snippet? Well, you'd get exactly the Rabin-Karp hash of string S. But since F(x) is a polynomial, we can use Horner's rule to compute the F(P). The resulting value might be very big, hence we use modular arithmetic:
static final long M = 83559671;
static final int Base = 13;
static long hash(String s, int from, int to) {
int iHash = 0;
for(int i = from; i < to; i++) {
iHash *= Base;
iHash += s.charAt(i);
iHash %= M;
}
return iHash;
}
You can use this function to obtain the hash of a string to be found in a text. And for initial window in the text. Then you can shift window and recalculate hash:
static void find(String pattern, String text) {
if(text.length() < pattern.length()) return;
int len = pattern.length();
long ph = hash(pattern, 0, len);
long h = hash(text, 0, len);
long basePower = mpow(Base, len);
if(h == ph) System.out.println("match at 0");
for(int i = len; i < text.length(); i++) {
h *= Base;
h += text.charAt(i);
h -= basePower * text.charAt(i - len);
h = mod(h);
if(h == ph) System.out.println("match at " + (i - len + 1));
}
}
static long mod(long a) {
a %= M;
if(a < 0) {
a += M;
}
return a;
}
static long mpow(long x, int k) {
long result = 1;
for(; k > 0; k >>= 1) {
if(k % 2 == 1) {
result = mod(result * x);
}
x = mod(x * x);
}
return result;
}
public static void main(String[] args) {
find("abracadabra", "abracadabracadabra");
}
For more information on this approach I recommend to refer to CLRS.
I have seen that such a function exists for BigInteger, i.e. BigInteger#gcd. Are there other functions in Java which also work for other types (int, long or Integer)? It seems this would make sense as java.lang.Math.gcd (with all kinds of overloads) but it is not there. Is it somewhere else?
(Don't confuse this question with "how do I implement this myself", please!)
As far as I know, there isn't any built-in method for primitives. But something as simple as this should do the trick:
public int gcd(int a, int b) {
if (b==0) return a;
return gcd(b,a%b);
}
You can also one-line it if you're into that sort of thing:
public int gcd(int a, int b) { return b==0 ? a : gcd(b, a%b); }
It should be noted that there is absolutely no difference between the two as they compile to the same byte code.
For int and long, as primitives, not really. For Integer, it is possible someone wrote one.
Given that BigInteger is a (mathematical/functional) superset of int, Integer, long, and Long, if you need to use these types, convert them to a BigInteger, do the GCD, and convert the result back.
private static int gcdThing(int a, int b) {
BigInteger b1 = BigInteger.valueOf(a);
BigInteger b2 = BigInteger.valueOf(b);
BigInteger gcd = b1.gcd(b2);
return gcd.intValue();
}
Or the Euclidean algorithm for calculating the GCD...
public int egcd(int a, int b) {
if (a == 0)
return b;
while (b != 0) {
if (a > b)
a = a - b;
else
b = b - a;
}
return a;
}
Unless I have Guava, I define like this:
int gcd(int a, int b) {
return a == 0 ? b : gcd(b % a, a);
}
Use Guava LongMath.gcd() and IntMath.gcd()
Jakarta Commons Math has exactly that.
ArithmeticUtils.gcd(int p, int q)
You can use this implementation of Binary GCD algorithm
public class BinaryGCD {
public static int gcd(int p, int q) {
if (q == 0) return p;
if (p == 0) return q;
// p and q even
if ((p & 1) == 0 && (q & 1) == 0) return gcd(p >> 1, q >> 1) << 1;
// p is even, q is odd
else if ((p & 1) == 0) return gcd(p >> 1, q);
// p is odd, q is even
else if ((q & 1) == 0) return gcd(p, q >> 1);
// p and q odd, p >= q
else if (p >= q) return gcd((p-q) >> 1, q);
// p and q odd, p < q
else return gcd(p, (q-p) >> 1);
}
public static void main(String[] args) {
int p = Integer.parseInt(args[0]);
int q = Integer.parseInt(args[1]);
System.out.println("gcd(" + p + ", " + q + ") = " + gcd(p, q));
}
}
From http://introcs.cs.princeton.edu/java/23recursion/BinaryGCD.java.html
Some implementations here are not working correctly if both numbers are negative. gcd(-12, -18) is 6, not -6.
So an absolute value should be returned, something like
public static int gcd(int a, int b) {
if (b == 0) {
return Math.abs(a);
}
return gcd(b, a % b);
}
we can use recursive function for find gcd
public class Test
{
static int gcd(int a, int b)
{
// Everything divides 0
if (a == 0 || b == 0)
return 0;
// base case
if (a == b)
return a;
// a is greater
if (a > b)
return gcd(a-b, b);
return gcd(a, b-a);
}
// Driver method
public static void main(String[] args)
{
int a = 98, b = 56;
System.out.println("GCD of " + a +" and " + b + " is " + gcd(a, b));
}
}
public int gcd(int num1, int num2) {
int max = Math.abs(num1);
int min = Math.abs(num2);
while (max > 0) {
if (max < min) {
int x = max;
max = min;
min = x;
}
max %= min;
}
return min;
}
This method uses the Euclid’s algorithm to get the "Greatest Common Divisor" of two integers. It receives two integers and returns the gcd of them. just that easy!
If you are using Java 1.5 or later then this is an iterative binary GCD algorithm which uses Integer.numberOfTrailingZeros() to reduce the number of checks and iterations required.
public class Utils {
public static final int gcd( int a, int b ){
// Deal with the degenerate case where values are Integer.MIN_VALUE
// since -Integer.MIN_VALUE = Integer.MAX_VALUE+1
if ( a == Integer.MIN_VALUE )
{
if ( b == Integer.MIN_VALUE )
throw new IllegalArgumentException( "gcd() is greater than Integer.MAX_VALUE" );
return 1 << Integer.numberOfTrailingZeros( Math.abs(b) );
}
if ( b == Integer.MIN_VALUE )
return 1 << Integer.numberOfTrailingZeros( Math.abs(a) );
a = Math.abs(a);
b = Math.abs(b);
if ( a == 0 ) return b;
if ( b == 0 ) return a;
int factorsOfTwoInA = Integer.numberOfTrailingZeros(a),
factorsOfTwoInB = Integer.numberOfTrailingZeros(b),
commonFactorsOfTwo = Math.min(factorsOfTwoInA,factorsOfTwoInB);
a >>= factorsOfTwoInA;
b >>= factorsOfTwoInB;
while(a != b){
if ( a > b ) {
a = (a - b);
a >>= Integer.numberOfTrailingZeros( a );
} else {
b = (b - a);
b >>= Integer.numberOfTrailingZeros( b );
}
}
return a << commonFactorsOfTwo;
}
}
Unit test:
import java.math.BigInteger;
import org.junit.Test;
import static org.junit.Assert.*;
public class UtilsTest {
#Test
public void gcdUpToOneThousand(){
for ( int x = -1000; x <= 1000; ++x )
for ( int y = -1000; y <= 1000; ++y )
{
int gcd = Utils.gcd(x, y);
int expected = BigInteger.valueOf(x).gcd(BigInteger.valueOf(y)).intValue();
assertEquals( expected, gcd );
}
}
#Test
public void gcdMinValue(){
for ( int x = 0; x < Integer.SIZE-1; x++ ){
int gcd = Utils.gcd(Integer.MIN_VALUE,1<<x);
int expected = BigInteger.valueOf(Integer.MIN_VALUE).gcd(BigInteger.valueOf(1<<x)).intValue();
assertEquals( expected, gcd );
}
}
}
Is it somewhere else?
Apache! - it has both gcd and lcm, so cool!
However, due to profoundness of their implementation, it's slower compared to simple hand-written version (if it matters).
/*
import scanner and instantiate scanner class;
declare your method with two parameters
declare a third variable;
set condition;
swap the parameter values if condition is met;
set second conditon based on result of first condition;
divide and assign remainder to the third variable;
swap the result;
in the main method, allow for user input;
Call the method;
*/
public class gcf {
public static void main (String[]args){//start of main method
Scanner input = new Scanner (System.in);//allow for user input
System.out.println("Please enter the first integer: ");//prompt
int a = input.nextInt();//initial user input
System.out.println("Please enter a second interger: ");//prompt
int b = input.nextInt();//second user input
Divide(a,b);//call method
}
public static void Divide(int a, int b) {//start of your method
int temp;
// making a greater than b
if (b > a) {
temp = a;
a = b;
b = temp;
}
while (b !=0) {
// gcd of b and a%b
temp = a%b;
// always make a greater than b
a =b;
b =temp;
}
System.out.println(a);//print to console
}
}
I used this method that I created when I was 14 years old.
public static int gcd (int a, int b) {
int s = 1;
int ia = Math.abs(a);//<-- turns to absolute value
int ib = Math.abs(b);
if (a == b) {
s = a;
}else {
while (ib != ia) {
if (ib > ia) {
s = ib - ia;
ib = s;
}else {
s = ia - ib;
ia = s;
}
}
}
return s;
}
Those GCD functions provided by Commons-Math and Guava have some differences.
Commons-Math throws an ArithematicException.class only for Integer.MIN_VALUE or Long.MIN_VALUE.
Otherwise, handles the value as an absolute value.
Guava throws an IllegalArgumentException.class for any negative values.
The % going to give us the gcd Between two numbers, it means:-
% or mod of big_number/small_number are =gcd,
and we write it on java like this big_number % small_number.
EX1: for two integers
public static int gcd(int x1,int x2)
{
if(x1>x2)
{
if(x2!=0)
{
if(x1%x2==0)
return x2;
return x1%x2;
}
return x1;
}
else if(x1!=0)
{
if(x2%x1==0)
return x1;
return x2%x1;
}
return x2;
}
EX2: for three integers
public static int gcd(int x1,int x2,int x3)
{
int m,t;
if(x1>x2)
t=x1;
t=x2;
if(t>x3)
m=t;
m=x3;
for(int i=m;i>=1;i--)
{
if(x1%i==0 && x2%i==0 && x3%i==0)
{
return i;
}
}
return 1;
}