/* euclid.c
*
* Rational arithmetic routines
*
*
*
* SYNOPSIS :
*
*
* typedef struct
* {
* double n ; numerator
* double d ; denominator
* } fract ;
*
* radd ( a , b , c ) c = b + a
* rsub ( a , b , c ) c = b - a
* rmul ( a , b , c ) c = b * a
* rdiv ( a , b , c ) c = b / a
* euclid ( & n , & d ) Reduce n / d to lowest terms ,
* return greatest common divisor .
*
* Arguments of the routines are pointers to the structures .
* The double precision numbers are assumed , without checking ,
* to be integer valued . Overflow conditions are reported .
*/
#include "mconf.h"
#ifdef ANSIPROT
extern double fabs ( double );
extern double floor ( double );
double euclid( double *, double * );
#else
double fabs(), floor(), euclid();
#endif
extern double MACHEP;
#define BIG (1 .0 /MACHEP)
typedef struct
{
double n; /* numerator */
double d; /* denominator */
}fract;
/* Add fractions. */
void radd( f1, f2, f3 )
fract *f1, *f2, *f3;
{
double gcd, d1, d2, gcn, n1, n2;
n1 = f1->n;
d1 = f1->d;
n2 = f2->n;
d2 = f2->d;
if ( n1 == 0 .0 )
{
f3->n = n2;
f3->d = d2;
return ;
}
if ( n2 == 0 .0 )
{
f3->n = n1;
f3->d = d1;
return ;
}
gcd = euclid( &d1, &d2 ); /* common divisors of denominators */
gcn = euclid( &n1, &n2 ); /* common divisors of numerators */
/* Note, factoring the numerators
* makes overflow slightly less likely .
*/
f3->n = ( n1 * d2 + n2 * d1) * gcn;
f3->d = d1 * d2 * gcd;
euclid( &f3->n, &f3->d );
}
/* Subtract fractions. */
void rsub( f1, f2, f3 )
fract *f1, *f2, *f3;
{
double gcd, d1, d2, gcn, n1, n2;
n1 = f1->n;
d1 = f1->d;
n2 = f2->n;
d2 = f2->d;
if ( n1 == 0 .0 )
{
f3->n = n2;
f3->d = d2;
return ;
}
if ( n2 == 0 .0 )
{
f3->n = -n1;
f3->d = d1;
return ;
}
gcd = euclid( &d1, &d2 );
gcn = euclid( &n1, &n2 );
f3->n = (n2 * d1 - n1 * d2) * gcn;
f3->d = d1 * d2 * gcd;
euclid( &f3->n, &f3->d );
}
/* Multiply fractions. */
void rmul( ff1, ff2, ff3 )
fract *ff1, *ff2, *ff3;
{
double d1, d2, n1, n2;
n1 = ff1->n;
d1 = ff1->d;
n2 = ff2->n;
d2 = ff2->d;
if ( (n1 == 0 .0 ) || (n2 == 0 .0 ) )
{
ff3->n = 0 .0 ;
ff3->d = 1 .0 ;
return ;
}
euclid( &n1, &d2 ); /* cross cancel common divisors */
euclid( &n2, &d1 );
ff3->n = n1 * n2;
ff3->d = d1 * d2;
/* Report overflow. */
if ( (fabs(ff3->n) >= BIG) || (fabs(ff3->d) >= BIG) )
{
mtherr( "rmul" , OVERFLOW );
return ;
}
/* euclid( &ff3->n, &ff3->d );*/
}
/* Divide fractions. */
void rdiv( ff1, ff2, ff3 )
fract *ff1, *ff2, *ff3;
{
double d1, d2, n1, n2;
n1 = ff1->d; /* Invert ff1, then multiply */
d1 = ff1->n;
if ( d1 < 0 .0 )
{ /* keep denominator positive */
n1 = -n1;
d1 = -d1;
}
n2 = ff2->n;
d2 = ff2->d;
if ( (n1 == 0 .0 ) || (n2 == 0 .0 ) )
{
ff3->n = 0 .0 ;
ff3->d = 1 .0 ;
return ;
}
euclid( &n1, &d2 ); /* cross cancel any common divisors */
euclid( &n2, &d1 );
ff3->n = n1 * n2;
ff3->d = d1 * d2;
/* Report overflow. */
if ( (fabs(ff3->n) >= BIG) || (fabs(ff3->d) >= BIG) )
{
mtherr( "rdiv" , OVERFLOW );
return ;
}
/* euclid( &ff3->n, &ff3->d );*/
}
/* Euclidean algorithm
* reduces fraction to lowest terms ,
* returns greatest common divisor .
*/
double euclid( num, den )
double *num, *den;
{
double n, d, q, r;
n = *num; /* Numerator. */
d = *den; /* Denominator. */
/* Make numbers positive, locally. */
if ( n < 0 .0 )
n = -n;
if ( d < 0 .0 )
d = -d;
/* Abort if numbers are too big for integer arithmetic. */
if ( (n >= BIG) || (d >= BIG) )
{
mtherr( "euclid" , OVERFLOW );
return (1 .0 );
}
/* Divide by zero, gcd = 1. */
if (d == 0 .0 )
return ( 1 .0 );
/* Zero. Return 0/1, gcd = denominator. */
if (n == 0 .0 )
{
/*
if ( * den < 0 . 0 )
* den = - 1 . 0 ;
else
* den = 1 . 0 ;
*/
*den = 1 .0 ;
return ( d );
}
while ( d > 0 .5 )
{
/* Find integer part of n divided by d. */
q = floor( n/d );
/* Find remainder after dividing n by d. */
r = n - d * q;
/* The next fraction is d/r. */
n = d;
d = r;
}
if ( n < 0 .0 )
mtherr( "euclid" , UNDERFLOW );
*num /= n;
*den /= n;
return ( n );
}
Messung V0.5 in Prozent C=89 H=97 G=93
¤ Dauer der Verarbeitung: 0.9 Sekunden
(vorverarbeitet am 2026-06-15)
¤
*© Formatika GbR, Deutschland