# fractions in c - a rational arithmetic library

chris (2008-11-09 00:19:17)
6441 views
2 replies

I got carried away today. After a brief IM conversation with a friend late last night, I went to bed with an urge to write this rational arithmetic library. With the baby asleep and the wife not looking, I set to work.. beer in hand.. and this is the result.

Interesting bits: using a struct typedef to pre-define the 'rational' datatype, also the use of recursion in the 'reduce' function to further reduce the fractional part of a rational number which has already been reduced from being top-heavy.

Caveats - this version doesn't play nice when values fall below zero - However, the latest update (scroll down the page to the second reply) does.

```#include <stdlib.h> #include <stdio.h> #include <string.h> typedef struct { int integer; int numerator; int denominator; } rational; rational add ( rational *r, rational *r2 ); rational subtract ( rational *r, rational *r2 ); rational multiply ( rational *r, rational *r2); rational divide ( rational *r, rational *r2); rational reduce ( rational *r ); void display ( rational *r ); int main( int argc, char *argv[]){ rational rational1, rational2, result; printf("\nenter first numerator: "); scanf("%d", &rational1.numerator); printf("\nenter first denominator: "); scanf("%d", &rational1.denominator); printf("\nenter second numerator: "); scanf("%d", &rational2.numerator); printf("\nenter second denominator: "); scanf("%d", &rational2.denominator); result = add( &rational1, &rational2 ); result = reduce( &result ); printf("\nsum : "); display( &result); result = multiply( &rational1, &rational2 ); result = reduce( &result ); printf("\nproduct : "); display( &result); result = subtract( &rational1, &rational2 ); result = reduce( &result ); printf("\nsubtracted : "); display( &result); result = divide( &rational1, &rational2 ); result = reduce( &result ); printf("\ndivided : "); display( &result); printf("\n\n"); } void display ( rational *pr ){ if( pr->integer > 0 ){ printf("%d ",pr->integer); } if( pr->numerator > 0 && pr->denominator > 0){ printf("%d/%d",pr->numerator, pr->denominator); } } rational add ( rational *pr, rational *pr2 ){ rational result; int hcd; int nom1, nom2, tot; hcd = pr->denominator * pr2->denominator; nom1 = pr2->denominator * pr->numerator; nom2 = pr->denominator * pr2->numerator; tot = nom1 + nom2; result.numerator = tot; result.denominator = hcd; return result; } rational subtract ( rational *pr, rational *pr2 ){ rational result; int hcd; int nom1, nom2, tot; hcd = pr->denominator * pr2->denominator; nom1 = pr2->denominator * pr->numerator; nom2 = pr->denominator * pr2->numerator; tot = nom1 - nom2; result.numerator = tot; result.denominator = hcd; return result; } rational multiply ( rational *pr, rational *pr2 ){ rational result; result.numerator = pr->numerator * pr2->numerator; result.denominator = pr->denominator * pr2->denominator; return result; } rational divide ( rational *pr, rational *pr2 ){ rational result; result.numerator = pr->numerator * pr2->denominator; result.denominator = pr->denominator * pr2->numerator; return result; } rational reduce ( rational *pr ){ int i; rational result, fraction, reduced; /* fraction is fractional part of a proper function. This will recurse to further reduce the fraction */ if( pr->numerator > pr->denominator ){ if( (pr->numerator % pr->denominator) ==0 ){ /* this is a whole number */ result.integer = pr->numerator / pr->denominator; result.numerator = 0; result.denominator = 0; return result; } result.integer = (int)(pr->numerator / pr->denominator); result.numerator = pr->numerator - (pr->denominator * result.integer); result.denominator = pr->denominator; fraction.numerator = result.numerator; fraction.denominator = result.denominator; reduced = reduce (&fraction); result.numerator = reduced.numerator; result.denominator = reduced.denominator; return result; }else{ if( pr->numerator == pr->denominator ){ result.integer = 1; result.numerator = 0; result.denominator = 0; return result; } i = pr->numerator; while(i>0){ if(((pr->numerator % i) == 0 ) && ((pr->denominator %i ) == 0)){ result.integer = 0; result.numerator = ( pr->numerator / i ); result.denominator = ( pr->denominator / i ); return result; } i--; } return result; } } ```

christo
comment
chris
2008-11-09 22:06:01

## Improving slightly with Euclidean algorithm

This version uses the Euclidean algorithm to figure out the highest common factor in the reduce process.

```#include <stdlib.h> #include <stdio.h> #include <string.h> typedef struct { int integer; int numerator; int denominator; } rational; rational add ( rational *r, rational *r2 ); rational subtract ( rational *r, rational *r2 ); rational multiply ( rational *r, rational *r2); rational divide ( rational *r, rational *r2); rational reduce ( rational *r ); void display ( rational *r ); int hcf ( int, int ); int main( int argc, char *argv[]){ rational rational1, rational2, result; printf("\nenter first numerator: "); scanf("%d", &rational1.numerator); printf("\nenter first denominator: "); scanf("%d", &rational1.denominator); printf("\nenter second numerator: "); scanf("%d", &rational2.numerator); printf("\nenter second denominator: "); scanf("%d", &rational2.denominator); result = add( &rational1, &rational2 ); result = reduce( &result ); printf("nsum : "); display( &result); result = multiply( &rational1, &rational2 ); result = reduce( &result ); printf("\nproduct : "); display( &result); result = subtract( &rational1, &rational2 ); result = reduce( &result ); printf("\nsubtracted : "); display( &result); result = divide( &rational1, &rational2 ); result = reduce( &result ); printf("\ndivided : "); display( &result); printf("\n\n"); } void display ( rational *pr ){ if( pr->integer > 0 ){ printf("%d ",pr->integer); } if( pr->numerator > 0 && pr->denominator > 0){ printf("%d/%d",pr->numerator, pr->denominator); } } rational add ( rational *pr, rational *pr2 ){ rational result; int hcd; int nom1, nom2, tot; hcd = pr->denominator * pr2->denominator; nom1 = pr2->denominator * pr->numerator; nom2 = pr->denominator * pr2->numerator; tot = nom1 + nom2; result.numerator = tot; result.denominator = hcd; return result; } rational subtract ( rational *pr, rational *pr2 ){ rational result; int hcd; int nom1, nom2, tot; hcd = pr->denominator * pr2->denominator; nom1 = pr2->denominator * pr->numerator; nom2 = pr->denominator * pr2->numerator; tot = nom1 - nom2; result.numerator = tot; result.denominator = hcd; return result; } rational multiply ( rational *pr, rational *pr2 ){ rational result; result.numerator = pr->numerator * pr2->numerator; result.denominator = pr->denominator * pr2->denominator; return result; } rational divide ( rational *pr, rational *pr2 ){ rational result; result.numerator = pr->numerator * pr2->denominator; result.denominator = pr->denominator * pr2->numerator; return result; } rational reduce ( rational *pr ){ int i; rational result, fraction, reduced; /* fraction is fractional part of a proper function. This will recurse to further reduce the fraction */ if( pr->numerator > pr->denominator ){ if( (pr->numerator % pr->denominator) ==0 ){ /* this is a whole number */ result.integer = pr->numerator / pr->denominator; result.numerator = 0; result.denominator = 0; return result; } result.integer = (int)(pr->numerator / pr->denominator); result.numerator = pr->numerator - (pr->denominator * result.integer); result.denominator = pr->denominator; fraction.numerator = result.numerator; fraction.denominator = result.denominator; reduced = reduce (&fraction); result.numerator = reduced.numerator; result.denominator = reduced.denominator; return result; }else{ if( pr->numerator == pr->denominator ){ result.integer = 1; result.numerator = 0; result.denominator = 0; return result; } i = hcf( pr->numerator, pr->denominator ); result.integer = 0; result.numerator = ( pr->numerator / i ); result.denominator = ( pr->denominator / i ); return result; } } int hcf(int i, int j) { if( j == 0 ){ return i; }else{ hcf(j, i % j); } } ```
christo
chris
2008-11-27 08:34:08

## fixed negative number issues

It was annoying me, so I have fixed the issues with negative numbers, which sometimes occur as a result of the subtract() function. This version is very solid. Next iteration, I will allow the user to provide the integer part, allowing proper fractions > 1.

```#include <stdlib.h> #include <stdio.h> #include <string.h> typedef struct { int integer; int numerator; int denominator; } rational; rational add ( rational *r, rational *r2 ); rational subtract ( rational *r, rational *r2 ); rational multiply ( rational *r, rational *r2); rational divide ( rational *r, rational *r2); rational reduce ( rational *r ); void display ( rational *r ); int hcf ( int, int ); int main( int argc, char *argv[]){ rational rational1, rational2, result; printf("\nenter first numerator: "); scanf("%d", &rational1.numerator); printf("\nenter first denominator: "); scanf("%d", &rational1.denominator); printf("\nenter second numerator: "); scanf("%d", &rational2.numerator); printf("\nenter second denominator: "); scanf("%d", &rational2.denominator); result = add( &rational1, &rational2 ); result = reduce( &result ); printf("\nsum : "); display( &result); result = multiply( &rational1, &rational2 ); result = reduce( &result ); printf("\nproduct : "); display( &result); result = subtract( &rational1, &rational2 ); result = reduce( &result ); printf("\nsubtracted : "); display( &result); result = divide( &rational1, &rational2 ); result = reduce( &result ); printf("\ndivided : "); display( &result); printf("\n\n"); } void display ( rational *pr ){ if( pr->integer > 0 ){ printf("%d ",pr->integer); } if( pr->numerator < 0 || pr->denominator < 0){ if(pr->numerator < 0){ pr->numerator *= -1; } if(pr->denominator < 0){ pr->denominator *= -1; } printf("-"); } printf("%d/%d",pr->numerator, pr->denominator); } rational add ( rational *pr, rational *pr2 ){ rational result; int hcd; int nom1, nom2, tot; result.integer = 0; hcd = pr->denominator * pr2->denominator; nom1 = pr2->denominator * pr->numerator; nom2 = pr->denominator * pr2->numerator; tot = nom1 + nom2; result.numerator = tot; result.denominator = hcd; return result; } rational subtract ( rational *pr, rational *pr2 ){ rational result; int hcd; int nom1, nom2, tot; hcd = pr->denominator * pr2->denominator; nom1 = pr2->denominator * pr->numerator; nom2 = pr->denominator * pr2->numerator; tot = nom1 - nom2; result.numerator = tot; result.denominator = hcd; return result; } rational multiply ( rational *pr, rational *pr2 ){ rational result; result.numerator = pr->numerator * pr2->numerator; result.denominator = pr->denominator * pr2->denominator; return result; } rational divide ( rational *pr, rational *pr2 ){ rational result; result.numerator = pr->numerator * pr2->denominator; result.denominator = pr->denominator * pr2->numerator; return result; } rational reduce ( rational *pr ){ int i, neg; rational result, fraction, reduced, returnresult; /* set a flag if there is a -ve component */ neg = 0; if( pr->integer < 0 || pr->numerator < 0 || pr->denominator < 0 ){ neg = 1; } /* set all components to their positive magnitude */ pr->integer = (pr->integer < 0) ? pr->integer * -1 : pr->integer; pr->numerator = (pr->numerator < 0) ? pr->numerator * -1 : pr->numerator; pr->denominator = (pr->denominator < 0) ? pr->denominator * -1 : pr->denominator; /* fraction is fractional part of a proper function. This will recurse to further reduce the fraction */ /* should test magnitude not difference */ if( pr->numerator > pr->denominator ){ if( (pr->numerator % pr->denominator) ==0 ){ /* this is a whole number */ result.integer = pr->numerator / pr->denominator; result.numerator = 0; result.denominator = 0; returnresult = result; }else{ result.integer = (int)(pr->numerator / pr->denominator); result.numerator = pr->numerator - (pr->denominator * result.integer); result.denominator = pr->denominator; fraction.integer = result.integer; fraction.numerator = result.numerator; fraction.denominator = result.denominator; reduced = reduce (&fraction); result.numerator = reduced.numerator; result.denominator = reduced.denominator; returnresult = result; } }else{ if( pr->numerator == pr->denominator ){ result.integer = 1; result.numerator = 0; result.denominator = 0; returnresult = result; } i = hcf( pr->numerator, pr->denominator ); result.integer = 0; result.numerator = ( pr->numerator / i ); result.denominator = ( pr->denominator / i ); returnresult = result; } /* before returning, negate if necessary */ if( neg == 1 ){ if( returnresult.integer > 0 ){ returnresult.integer *= -1; }else{ returnresult.numerator *= -1; } } return returnresult; } int hcf(int i, int j) { if( j == 0 ){ return i; }else{ hcf(j, i % j); } } ```