|
[SUB] Fractions
#472704
05/15/18 10:44
05/15/18 10:44
|
Joined: Jun 2007
Posts: 1,337 Hiporope and its pain
txesmi
OP
Serious User
|
OP
Serious User
Joined: Jun 2007
Posts: 1,337
Hiporope and its pain
|
Hi! I wrote a little module to work with fractions. ifractions.h
#ifndef _IFRACTIONS_H_
#define _IFRACTIONS_H_
#define TEMPFRAC_COUNT 16
typedef struct IFRAC {
int num;
int den;
} IFRAC;
IFRAC *ifraction(int _num, int _den); // temporal ifrac
IFRAC *ifracSet(IFRAC *_ifracA, IFRAC *_ifracB);
IFRAC *ifracAdd(IFRAC *_ifracA, IFRAC *_ifracB);
IFRAC *ifracSub(IFRAC *_ifracA, IFRAC *_ifracB);
IFRAC *ifracDiff(IFRAC *_ifracR, IFRAC *_ifracA, IFRAC *_ifracB);
IFRAC *ifracMul(IFRAC *_ifracA, IFRAC *_ifracB);
IFRAC *ifracDiv(IFRAC *_ifracA, IFRAC *_ifracB);
IFRAC *ifracSimplify(IFRAC *_ifrac);
IFRAC *ifracCommonDen(IFRAC *_ifracA, IFRAC *_ifracB);
var ifracToNum(IFRAC *_ifrac);
IFRAC *ifracForNum(IFRAC *_ifrac, var _n);
void ifracPrintf(IFRAC *_ifrac);
#include "ifractions.c"
#endif
ifractions.c
int _mathGCD(int _a, int _b) {
for (;;) {
if (_a == 0)
return _b;
_b %= _a;
if (_b == 0)
return _a;
_a %= _b;
}
}
int _mathLCM(int _a, int _b) {
int _t = _mathGCD(_a, _b);
if (!_t)
return 0;
return _a / _t * _b;
}
IFRAC _ifracTemp[TEMPFRAC_COUNT];
IFRAC *_ifracZero = {num = 0; den = 1;}
IFRAC *ifraction(int _num, int _den) {
static int _i = 0;
IFRAC *_ifrac = _ifracTemp + _i;
_i = (_i + 1) % TEMPFRAC_COUNT;
memcpy(_ifrac, &_num, sizeof(IFRAC));
return ifracSimplify(_ifrac);
}
IFRAC *ifracSet(IFRAC *_ifracA, IFRAC *_ifracB) {
memcpy(_ifracA, _ifracB, sizeof(IFRAC));
return ifracSimplify(_ifracA);
}
IFRAC *ifracSimplify(IFRAC *_ifrac) {
int _gcd = _mathGCD(abs(_ifrac->num), abs(_ifrac->den));
if (_gcd) {
_ifrac->num /= _gcd;
_ifrac->den /= _gcd;
}
if ((_ifrac->num == 0) || (_ifrac->den == 0)) {
memcpy(_ifrac, _ifracZero, sizeof(IFRAC));
} else if (_ifrac->den < 0) {
_ifrac->num *= -1;
_ifrac->den *= -1;
}
return _ifrac;
}
IFRAC *ifracCommonDen(IFRAC *_ifracA, IFRAC *_ifracB) {
int _lcm = _mathLCM(_ifracA->den, _ifracB->den);
_ifracA->num *= _lcm / _ifracA->den;
_ifracA->den = _lcm;
_ifracB->num *= _lcm / _ifracB->den;
_ifracB->den = _lcm;
return _ifracA;
}
IFRAC *ifracAdd(IFRAC *_ifracA, IFRAC *_ifracB) {
IFRAC *_ifracT = ifraction(_ifracB->num, _ifracB->den);
ifracCommonDen(_ifracA, _ifracT);
_ifracA->num += _ifracT->num;
return ifracSimplify(_ifracA);
}
IFRAC *ifracSub(IFRAC *_ifracA, IFRAC *_ifracB) {
IFRAC *_ifracT = ifraction(_ifracB->num, _ifracB->den);
ifracCommonDen(_ifracA, _ifracT);
_ifracA->num -= _ifracT->num;
return ifracSimplify(_ifracA);
}
IFRAC *ifracDiff(IFRAC *_ifracR, IFRAC *_ifracA, IFRAC *_ifracB) {
ifracSet(_ifracR, _ifracA);
return ifracSub(_ifracR, _ifracB);
}
IFRAC *ifracMul(IFRAC *_ifracA, IFRAC *_ifracB) {
_ifracA->num *= _ifracB->num;
_ifracA->den *= _ifracB->den;
return ifracSimplify(_ifracA);
}
IFRAC *ifracDiv(IFRAC *_ifracA, IFRAC *_ifracB) {
_ifracA->num *= _ifracB->den;
_ifracA->den *= _ifracB->num;
return ifracSimplify(_ifracA);
}
var ifracToNum(IFRAC *_ifrac) {
return (var)_ifrac->num / _ifrac->den;
}
IFRAC *ifracForNum(IFRAC *_ifrac, var _n) {
_ifrac->num = _n << 10;
_ifrac->den = 1024;
return ifracSimplify(_ifrac);
}
void ifracPrintf(IFRAC *_ifrac) {
printf("%d / %d", _ifrac->num, _ifrac->den);
}
Maybe a bit overheaded of simplification. Enjoy!
Last edited by txesmi; 05/15/18 11:40. Reason: error!! fixed
|
|
|
|