From edcded21cbeb272ff206a92c693ab21bf33ebae6 Mon Sep 17 00:00:00 2001 From: Julian Weigt Date: Tue, 23 Dec 2025 15:55:51 +0000 Subject: Define safe sums and products and finish exact version. --- ratio.c | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 84 insertions(+), 23 deletions(-) (limited to 'ratio.c') diff --git a/ratio.c b/ratio.c index 8c67538..70a198a 100644 --- a/ratio.c +++ b/ratio.c @@ -1,64 +1,125 @@ #include #include #include +#include -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; +} -- cgit v1.2.3