[ fresh.bm @ 25.07.2009. 13:33 ] @
Radim program koji vrsi matematicka izracunavanja ali sam naisao na problem.

Kada mi se u procesu racunanja javi broj npr. 22.5, 38.5, funkcija round() iz biblioteke math.h mi zaokruzuje te brojeve na 23, 39.
Meni treba funkcija koja ce vrsiti zaokruzivanje po principu da ako je parna cifra ne dirati broj,
ne odgovara mi funkcija floor, zato sto u slucaju neparnog broja round() dobro zaokruzuje,
kako da resim problem, nisam uspio naci ni jednu funkciju u c-u koja ce mi obaviti ovaj posao a rijec je o nekoliko hiljada izracunavanja koja moraju biti zaokruzena po tim pravilima. To mi pravi ogroman problem, jer klijent zahtjeva bas takav princip zaokruzivanja.
Molim za pomoc, hvala.
[ kiklop74 @ 25.07.2009. 18:48 ] @
http://www.elook.org/programming/c/floor.html
[ Mihajlo Cvetanović @ 26.07.2009. 23:01 ] @
Neverovatno da ne mogu da nađem odgovarajuću funkciju nigde na Internetu! To zaokruživanje se zove "round to even", dat je opis algoritma na Vikipediji (u članku Rounding), ali nigde nema funkcija koja bi to efikasno implementirala u C++-u. Evo meta-koda iz glave (ovde pretpostavljam da je floor funkcija efikasnija od množenja za ispitivanje graničnog slučaja):

Code:

f = floor(x);

if (x - f == .5)
  return f + (f % 2 ? 1 : 0);
else
  return round(x);
[ Mihajlo Cvetanović @ 27.07.2009. 13:38 ] @
Evo i efikasnije varijante (isto iz glave, treba je testirati):

Code:

r = round(x);

return (r % 2 == 1 && r - x == 0.5) ? r - 1 : r;
[ mmix @ 27.07.2009. 16:50 ] @
Ok, sad pregledah svoje "k u p u s a r e" i zaista nema jednostavnog resenja.
Algoritam koji ja imam se svodi na vase resenje sa floor ali u modifikovanoj varijatni posto ne bi trebalo porediti rezultat fp operacije sa ==. Npr 3.5-3 moze biti 0.5 ali moze biti i 0.500000001 ili slicno u zavisnosti od implementacije i tacnosti runtime-a, isto vazi i za sve ostale fp operacije, pa samim tim i za vrednosti koje se salju u round_half_even.
.NET je to resio kroz overload operator== koji vraca true ako je abs(x-y)<delta, za c/c++ mora da se povede racuna o nepreciznosti fp tipova. Ovu funkciju nisam pozvao godinama, pa proverite prvo dal radi...

Code:
double round_half_even(double x, const double delta) 
  {
    // symmetry, recurse on negative
    if (x < 0.0) return -round_half_even(-x, delta);

    // decompose 
    double i;
    double f = modf(x, &i);

    // are we "around .5"?
    if (abs(f-0.5) < delta) 
    {
        // is int even? if so we are there
        if (fmod(i, 2.0) < delta) return i;

        // if not, pump it up and round
        return round(i + 0.5);
    }

    // regular symmetric round
    return round(x);
}

[ Mihajlo Cvetanović @ 27.07.2009. 17:50 ] @
Da, i meni je to ispitivanje jednakosti sa 0.5 bolo oči. Možda bi moglo da se koristi i ceil(x - 0.5) != floor(x + 0.5), odnosno round(x) != -round(-x) (pitanje je kako je implementirana round funkcija).
[ mmix @ 27.07.2009. 20:45 ] @
ne mozes sa ceil i floor jer greska moze da prebaci u oba smera tj rezultat moze da bude 3.0000..001 ili 2.9999..999 sto daje dva razlicita ceil-a i floor-a . Ti fp brojevi su cudo
[ goran_7 @ 02.08.2009. 18:02 ] @
Izracunaj prvo izraz, pa onda iskoristi funkciju round('dobijena vrijednost'), meni je to pomoglo mozda ce i tebi.

Usput, moram postaviti pitanje u vezi zaokruzivanja float brojeva na odredjeni broj decimalnih mjesta.
Primjer, x = 2.34637382823 trebam zaokruziti na dvije decimale.
da li postoji standardna funkcija u C/C++-u? Ja je nisam nigdje nasao!
Moze li mi neko pomoci? Hvala.
Da ne dodje do zabune, ne trebam ispisivati brojeve sa dvije decimale, nego ih moram koristiti u racunanju, sto mi nakon nekoliko izracunavanja unese veliku gresku.
Hvala.