GCD if positive and negative numbers - c++

As mentioned here: gcd(a,b) = gcd(-a,b) = gcd(-a,-b). However when I use following code, I get different output for input being (-4,-8).
gcd(x,y) gives -4 wheras gcd(abs(x),abs(y)) gives 4.
Can some one help me understand where I am wrong.
int gcd(int a ,int b)
{
if(b==0)
return a;
return gcd(b,a%b);
}
int main()
{
int x,y;
cin>>x>>y;
cout<<gcd(x,y)<<endl; // gives -4
cout<<gcd(abs(x),abs(y))<<endl; //gives 4
return 0;
}

You're not taking into account that the output range has a plus or minus sign in it which breaks your algorithm, it's asserting that negative numbers and positive numbers are to be treated as the positive integers. Formal set theory in discrete mathematics has a different jargon set for symbols that are incompatible with most programming languages.
Greatest Common Denominator in C++ using recursion
int GCD(int A,int B)
{
if(A==0) return B;
if(B==0) return A;
A=abs(A);
B=abs(B);
if(A>B) return GCD(B,A);
return GCD(B%A,A);
}

Your algorithm cannot cover all positive and negative numbers. Use the code below.
int gcd(int a, int b){
a = abs(a);b = abs(b);
if (a == 0)
return b;
if (b == 0)
return a;
if (a == b)
return a;
if (a > b)
return gcd(a - b, b);
return gcd(a, b - a);
}

Related

Finding the count of numbers divisible by either of 3 values. How can it be more optimised

Three positive nos. A,B,C.Find no. of pos integers less than D divisible by either a,b,c. Well the test cases ran fine with one but for submitting it needed more optimised code. How can it be more optimised?
solve(int A, int B, int C, int D) {
int X = 0;
for (int i = 1; i < D; i++)
{
if (i%A==0 || i%B==0 || i%C==0)
{
X++;
}
}
return X;
}
The idea is simple take any number ,let it be 11,to find how many numbers are divisible by 3 we just need to find 11/3=3 i.e 3,6,9
Hence we add all the elements that are divisible by A or B or C.
But we also find that numbers like 24 are divisible by both 3 and 4 hence they will be counted twice if A=3 and B=4 so we subtract the amount that are divisible by both,i.e the ones divisible by lcm(3,4)=12. Similarly for the numbers divisible by all three should be added as it was subtracted multiple times.
Code is...
#include<iostream>
using namespace std;
int lcm(int a, int b);
int gcd(int a, int b);
int solve(int A,int B,int C,int D)
{
int divisibleA=D/A; //positive Numbers divisible by A
int divisibleB=D/B;
int divisibleC=D/C;
int divisible_A_B= D/(lcm(A,B)); //positive numbers that were divisible by A and B both These were counted twice
int divisible_A_C= D/(lcm(A,C));
int divisible_B_C= D/(lcm(B,C));
int divisible_A_B_C=D/lcm(lcm(A,B),C); //positive numbers divisible by all three
return divisibleA+divisibleB+divisibleC-divisible_A_B-divisible_A_C-divisible_B_C+ divisible_A_B_C;
}
int main()
{
int a,b,c,d;
cin>>a>>b>>c>>d;
cout<<solve(a,b,c,d)<<endl;
}
int gcd(int a, int b)
{
// base case
if (a == b)
return a;
// a is greater
if (a > b)
return gcd(a-b, b);
return gcd(a, b-a);
}
// Function to return LCM of two numbers
int lcm(int a, int b)
{
return (a*b)/gcd(a, b);
}
EDIT: The following should work:
int solve(const std::vector &array_of_numbers, int size, int divider){
int count = 0;
for (int i=0; i<size; i++){
if (array_of_numbers.at(i)%divider == 0){
count++;
}
}
return count;
}

How to calculate HCF a very large number and a small number without causing stack overflow. I am using euclid algorithm

I am using Euclid algorithm but it is causing run time error due to stack overflow.
I am unable to calculate HCF of a very large number and a small number
I believe you're writing a function like this:
int hcf(int a, int b){
if (a == 0){
return b;
}
else if (b == 0){
return a;
}
else if (a > b){
return hcf(b, a - b); // this is subtraction
}
else if (a < b){
return hcf(a, a - b); // this is subtraction
}
}
...and you're calling it with something like
int q = hcf(100000000, 1);
Well... Without optimisation that will create 1 billion recursion calls. It's definite that your program will run out of stack capacity.
My personally preferred solution is give up recursive methods and use an iterative one. The code can then be simplified to a single loop:
int hcf(int a, int b){
while(a != 0 && b != 0){
if (a > b){
a = a - b;
}
else{
b = b - a;
}
}
if (a == 0){
return b;
}
else{
return a;
}
}
If you insist on using recursive methods, replace subtraction with modulus.
else if (a > b){
-> return hcf(b, a % b); // this is modulus
}
else if (a < b){
-> return hcf(a, a % b); // this is modulus
}
Correctly implemented algorithm shall use at most log(number) steps, and thus not cause stack overflow. I suppose you use the following algorithm:
gcd(a, 0) = a
gcd(a, b) = gcd(a-b, b)
which looks like this in C++:
int gcd(int a, int b) {
if (b == 0) {
return a;
} else {
return gcd(std::max(a, b) - std::min(a, b), std::min(a, b));
}
}
This is not optimal. Instead you shall use the following relation
gcd(a, 0) = a
gcd(a, b) = gcd(b, a mod b)
which looks like this in C++:
int gcd(int a, int b) {
if (b == 0) {
return a;
} else {
return gcd(b, a % b);
}
}
This code will actually take only log(ab) steps, and thus not cause stack overflow
Also you may try to enable optimisation: it should allow to collapse both of the functions call into non-recursive versions (as this is a tail recursion). Note that it is not certain if it will increase speed.
As a matter of caution: be careful with the negative numbers, the % operator works incorrectly for them

Trying to calculate GCD in C++

I think I am not calling the function or passing it correctly. Here are a couple of snippets that I am having issues with.
Using test data, 1/2 and 8/16 returns 1/2 instead of 1/1.
This is my code to calculate the GCD:
void Fractions::gcd(int n, int d)
{
int a,b,c;
a = n;
b = d;
while (a%b != 0)
{
c = a % b;
a = b;
b = c;
}
num = n/b;
denom = d/b;
}
This is the code that calculates will add numbers from input and calculate the GCD based from those numbers:
Fractions Fractions::operator+(Fractions& fraction2)
{
Fractions totalAddition;
totalAddition.num = (num * fraction2.denom + denom * fraction2.num);
totalAddition.denom = (denom * fraction2.denom);
totalAddition.gcd(num, denom); // i think issue is here
return totalAddition;
}
The only problem here is the name of the function.
A function called gcd should return the Greatest Common Divisor:
int gcd(int n, int d) {
int a, b, c;
a = n;
b = d;
while (a % b != 0) {
c = a % b;
a = b;
b = c;
}
return b;
}
It doesn't need to be a member function of Fraction to do this - it can be a standalone function, which is better, as it makes Fraction more encapsulated. But you can give it an overload which digests Fraction:
int gcd(const Fraction& frac){
return gcd(frac.numerator(), frac.denominator());
}
The name gcd is on the terse side but clear enough in context.
What your function is doing is it's simplifying a fraction, as a member function of a Fraction object, and overwriting that Fraction's member variables. So, it should be called simplify, and it doesn't need to take any input:
void Fractions::simplify() {
int a, b, c;
a = num;
b = denom;
while (a % b != 0) {
c = a % b;
a = b;
b = c;
}
num = n / b;
denom = d / b;
}
You might find you don't need a gcd function in which case simplify will be enough. But if you do need both functions, you can avoid some duplication of code here:
void Fractions::simplify() {
int g = gcd(*this);
num /= g;
denom /= g;
}
//Euclidean algorithm
//if b<a the gcd(a,b)=gcd(a-b,b)
int gcd(int a,int b)
{
while(a!=b)
{
if(a>b)
a=a-b;
else
b=b-a;
}
return a;
}
Output
15 12
3
//Optimal implementation of Euclidean Algorithm
int gcd(int a,int b)
{
if(b==0)
return a;
else
return gcd(b,a%b);
}
Output
15 12
3

Function to determine whether 2 numbers are =, > or <

I have a question about a function to determinate if a number is >, = or < than another.
If I have for example:
int fun(int a, int b)
{
if (a > b)
return a;
else
if (b > a)
return b;
else
return 0
}
(I don't want to use any cout that interacts with the user).
Now if I give 2 numbers it gives me a, b or 0. But for example if a put in the function a = -1 and b = 0, the function clearly returns 0 even if the 2 numbers are not equal.
Yes, I could check before calling the function if the 2 numbers are the same. Or I could use a variable to see in which case I am, for example:
int fun(int a, int b)
{
int k = 0;
if (a > b)
return k;
else
if (b > a)
return k+1;
else
return k+2
}
But all these solutions are not so elegant. Is there a way to distinguish a 0 int from another? Or in any case is there a method to be sure that a return value come from a given point in this case?
You don't need else when the statement inside the if returns. I would additionally return something with actual meaning, rather than just an int. For example:
enum Relationship { LessThan = -1, Equal, GreaterThan};
if(a==b)
return Relationship::Equal;
if(a>b)
return Relationship::GreaterThan;
return Relationship::LessThan;
In general, I probably wouldn't bother writing a fucntion like this because managing this trinary output seems more effort than it's worth, but I'm assuming this is some kind of exercise.
You can use pointers
int* fun(int *a, int *b)
{
if (*a > *b)
return a;
else
if (*b > *a)
return b;
else
return NULL
}
if return value isn't NULL you can give maximum number from returned value

Adding two numbers without + operator (Clarification)

I know that we can use the logic of binary adder where Sum = a XOR b and Carry = a AND b
I have also got a solution:
int add(int a, int b)
{
if(b == 0)
return sum;
sum = a ^ b;
carry = (a & b) << 1;
return add(sum,carry);
}
What I don't understand here is why is the carry bit shifted, or multiplied by 2 during each recursion?
I find this a bit tricky to explain, but here's an attempt; think bit by bit addition, there are only 4 cases;
0+0=0
0+1=1
1+0=1
1+1=0 (and generates carry)
The two lines handle different cases
sum = a ^ b
Handles case 0+1 and 1+0, sum will contain the simple case, all bit positions that add up to 1.
carry = (a & b) << 1
The (a & b) part finds all bit positions with the case 1+1. Since the addition results in 0, it's the carry that's important, and it's shifted to the next position to the left (<<1). The carry needs to be added to that position, so the algorithm runs again.
The algorithm repeats until there are no more carries, in which case sum will contain the correct result.
Btw, return sum should be return a, then both sum and carry could be regular local variables.
public class AddSub {
int sum=0,carry=0;
public static void main(String[] args) {
System.out.println("Add "+new AddSub().addition(93,5));
System.out.println("Sub "+new AddSub().subtraction(7,60));
System.out.println("Sub "+new AddSub().multiplication(9,60));
}
public int addition(int a, int b)
{
if(b==0)
{
return a;
}
else
{
sum = a^b;
carry = (a&b)<<1;
return addition(sum,carry);
}
}
public int subtraction(int a, int b){
return addition(a,addition(~b,1));
}
public int multiplication(int a, int b){
for(int i=0;i<b/2;i++)
sum = addition(sum,addition(a,a));
return sum;
}
}
Hi don't be think yourself too difficult.
Here the simple way to do that.
Consider a=5, b=10;
c=a-(-b);
c=15;
that is it.