summaryrefslogtreecommitdiff
path: root/ratio.c
diff options
context:
space:
mode:
Diffstat (limited to 'ratio.c')
-rw-r--r--ratio.c107
1 files changed, 84 insertions, 23 deletions
diff --git a/ratio.c b/ratio.c
index 8c67538..70a198a 100644
--- a/ratio.c
+++ b/ratio.c
@@ -1,64 +1,125 @@
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
+#include <limits.h>
-typedef struct {long int n; long unsigned int d} rational;
+typedef unsigned long long num;
+
+typedef struct {bool s; num n; num d} rational;
+
+unsigned int safe_sum(num n1, num n2){
+ if(n2 > ULLONG_MAX-n1){
+ printf("Sum overflow: Adding %llu and %llu\n",n1,n2);
+ exit(1);
+ }
+ else {
+ return n1+n2;
+ }
+}
+
+num safe_product(num n1, num n2){
+ if(n1 != 0 && n2 > ULLONG_MAX/n1){
+ printf("Product overflow: Multiplying %llu by %llu\n",n1,n2);
+ exit(1);
+ }
+ else {
+ return n1*n2;
+ }
+}
rational convert_int(int i){
- rational r = {i,1};
+ rational r;
+ r.d = 1;
+ r.n = abs(i);
+ if(i >= 0) { r.s=false; } else { r.s=true; }
return r;
}
-rational cancel(rational r){
- long unsigned int a = abs(r.n), b = r.d, c;
+num gcd(num a, num b){
+ num c;
while (b) {
c = a % b;
a = b;
b = c;
}
- rational res = {r.n/a,r.d/a};
+ return a;
+}
+
+rational cancel(rational r){
+ num a = gcd(r.n,r.d);
+ rational res = {r.s,r.n/a,r.d/a};
return res;
}
rational sum(rational r1, rational r2){
- rational r = {r1.n*r2.d+r2.n*r1.d,r1.d*r2.d};
+ num a = gcd(r1.d,r2.d);
+ num r1da = r1.d/a;
+ num r2da = r2.d/a;
+ rational r;
+ r.d = safe_product(r1da,r2.d);
+ num n1 = safe_product(r1.n,r2da);
+ num n2 = safe_product(r2.n,r1da);
+ if(r1.s == r2.s){
+ r.n = safe_sum(n1,n2);
+ r.s = r1.s;
+ }
+ else {
+ if(n1 >= n2) {
+ r.n = n1 - n2;
+ r.s = r1.s;
+ }
+ else {
+ r.n = n2 - n1;
+ r.s = r2.s;
+ }
+ }
return cancel(r);
}
rational difference(rational r1, rational r2){
- rational r = {r1.n*r2.d-r2.n*r1.d,r1.d*r2.d};
- return cancel(r);
+ r2.s = !r2.s;
+ return sum(r1,r2);
}
-bool is_greater(rational r1, rational r2){ return (difference(r1,r2).n > 0); }
+bool is_greater(rational r1, rational r2){ return !(difference(r1,r2).s); }
rational product(rational r1, rational r2){
- rational r = {r1.n*r2.n,r1.d*r2.d};
+ rational r;
+ rational s1 = {r1.s, r1.n, r2.d};
+ rational s2 = {r2.s, r2.n, r1.d};
+ rational t1 = cancel(s1);
+ rational t2 = cancel(s2);
+ r.s = t1.s^t2.s;
+ r.n = safe_product(t1.n,t2.n);
+ r.d = safe_product(t1.d,t2.d);
return cancel(r);
}
rational ratio(rational r1, rational r2){
- rational r = {0,1};
- if (r2.n>0){
- rational r = {0,1};
- }
- else{
- rational r = {-r1.n*r2.d,r1.d*(-r2.n)};
- }
- return cancel(r);
+ rational r2i = {r2.s,r2.d,r2.n};
+ return product(r1,r2i);
}
-double to_double(rational r){ return ((double)r.n)/((double)r.d); }
-
rational absolute(rational r){
- rational s = {abs(r.n),r.d};
+ rational s = {false,r.n,r.d};
return s;
}
rational power(rational r, unsigned int p){
- rational s = {1,1};
+ rational s = {0,1,1};
for(int i = 1; i<= p; i++){
- rational s = product(r,s);
+ s = product(r,s);
}
return s;
}
+
+double to_double(rational r){
+ double i;
+ if(r.s) { i=-1.0; } else { i=1.0; }
+ return i*((double)r.n)/((double)r.d);
+}
+
+bool to_string(char* s,rational r){
+ sprintf(s,"%llu / %llu",r.n,r.d);
+ return true;
+}