közös nevező

Fórumok

Nincs véletlenül valakinek egy működő függvénye törtek közös nevezőre hozásához? Ami megbírkózik változó számú inputtal, és a törtek számláló/nevező alakban vannak tárolva mondjuk valamilyen struktúrában?

Hozzászólások

Nem optimális, de az átláthatóságra törekedtem. Hibakezelés nincs benne, úgyhogy ne tessék (1234 / 0)-val és olyasmikkel szívatni, aminél az int túlcsordul :)... (A változó számű paramétert lehetne vararg-osan is kezelni (man va_start), de arra már lusta vagyok.)


#include <stdio.h>
#include <stdlib.h>

int lnko(int a, int b) /* legnagyobb kozos oszto */
{
    int t;

    if (a < b)
    {
        t = a;
        a = b;
        b = t;
    }
    if (b == 0)
        return a;
    else
        return lnko(b, a % b);
}

int lkkt(int a, int b) /* legkisebb kozos tobbszoros */
{
    return a * (b / lnko(a, b));
}

typedef struct _tort_t
{
    int szamlalo, nevezo;
} tort_t;

void kozos_nevezore(int n, tort_t *t)
{
    int i, knev, sz;

    knev = 1;
    for (i = 0; i < n; i++)
    {
        /* egyszerusitsunk, ha lehet */
        sz = lnko(abs(t[i].szamlalo), abs(t[i].nevezo));
        /* nevezo ne legyen negativ */
        if (t[i].nevezo < 0)
            sz = -sz;
        t[i].szamlalo /= sz;
        t[i].nevezo /= sz;

        /* kozos nevezo = lkkt(eddigi kozos nevezo, ennek a tortnek a nevezoje) */
        knev = lkkt(knev, t[i].nevezo);
    }
    for (i = 0; i < n; i++)
    {
        sz = (knev / t[i].nevezo); /* bovitesi szorzo, hogy a nevezobol knev lehessen */;
        t[i].szamlalo *= sz;
        t[i].nevezo = knev;
    }
}

void kiir(int n, tort_t *t)
{
    int i;

    for (i = 0; i < n; i++)
        printf("(%d / %d) ", t[i].szamlalo, t[i].nevezo);
    printf("\n");
}

int main(int argc, char **argv)
{
    int n;
    tort_t tort[5];

    n = 5;
    tort[0].szamlalo =  1; tort[0].nevezo =  2; /* 1/2 */
    tort[1].szamlalo =  2; tort[1].nevezo =  3; /* 2/3 */
    tort[2].szamlalo = 30; tort[2].nevezo = 10; /* 30/10 = 3/1 */
    tort[3].szamlalo =  3; tort[3].nevezo =  5; /* 3/5 */
    tort[4].szamlalo =  7; tort[4].nevezo = 28; /* 7/28 = 1/4 */
    /* kozos nevezo = lkkt(2, 3, 1, 5, 4) = 60, igy a tortek:
     * 1/2 = 30/60, 2/3 = 40/60, 3/1 = 180/60, 3/5 = 36/60, 1/4 = 15/60 */

    printf("Eredetileg:\n");
    kiir(n, tort);

    kozos_nevezore(n, tort);
    printf("Kozos nevezore hozva:\n");
    kiir(n, tort);

    return 0;
}
// vim:ts=4:noexpandtab:cino='':shiftwidth=4:

Az lnko-t érdemes lenne rekurzió nélkül, mert úgy lényegesen gyorsabb, illetve meg kéne nézni maradékos osztás helyett kivonással, egymáshoz nagyságrendben közeli számoknál az gyorsabb.

Illetve lkkt-t lehet lnko nélkül, összeadásokkal, így megspórolnánk egy osztást.

Na ez rögtön 3 verzió, lehet benchmarkolni... :)

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

köszönöm mindenkinek a segítséget, elkészült a program és szépen működik is. sokat segítettetek, ezer köszönet!!!