CLang furcsasag

 ( hrgy84 | 2012. május 28., hétfő - 2:34 )

Mivel pinyo_villany olyan sokat irkal mostanaban a CLang-rol, kedvem tamadt kiprobalni. Fogtam is egy furcsasagot. Van egy ilyen kod, valahonnan a netrol:

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

int main() {
    float x,y,i,a=0.0;
    int s;
    for(s=0; s<10000; s++) {
        x=1.*rand()/RAND_MAX;
        y=1.*rand()/RAND_MAX;
        i+=x*x+y*y<=1;
        printf("%lf\n",4*i/++a);
    }
}

Az egyetlen modositas benne, hogy a clang sirt az a inicializalatlansaga miatt, azt inicializaltam.

A pi kornyekerol szamol random szamokat. Egy tipikus kimenet reszlete ilyen:

3.172224
3.171906
3.171588
3.171671
3.171754
3.171837

A GCC-vel forditott binaris mindig ilyet general, a CLang-os viszont minden 3-5. futasnal ilyet:

-14799051161600.000000
-14797566377984.000000
-14796081594368.000000
-14794597859328.000000
-14793113075712.000000
-14791629340672.000000
-14790145605632.000000

Nem pasztazom be mind a tizezer szamot, ami kijon beloluk, a minta elteres szemmel lathato.

Mintha idofuggo lenne, ha pihentetem egy kicsit (nem futtatom a clang-os kodot), akkor neha eleve a hibas kimenettel indul, utana megjavul, neha viszont jo kimenettel indul.

Otlet?

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

Az i nincs inicializálva, talán amiatt van. Viszont ami érdekes, a clang nem szólt emiatt, de a gcc szólt, pedig a clang-tól is vártam volna, hogy szól miatta.

$ clang -v
clang version 3.0 (tags/RELEASE_30/final)
Target: i686-w64-mingw32
Thread model: posix
$ clang -Wall -Wextra -o testcl.exe test.c
nincs kimenet

$ gcc -Wall -Wextra -o testgcc.exe test.c
test.c: In function 'main':
test.c:13:1: warning: control reaches end of non-void function [-Wreturn-type]
test.c:10:11: warning: 'i' may be used uninitialized in this function [-Wuninitialized]

Kipróbáltam én is, egyébként természetesen amiatt van.
Az, hogy nem visít érte, az fura nekem.
Megjegyzem: nálam a gcc sem.

Nalam sem.

# gcc version 4.5.1 20101208 [gcc-4_5-branch revision 167585] (SUSE Linux) 

$ gcc -Wall -Wextra -o pi.o pi.c
pi.c: In function ‘main’:
pi.c:13:1: warning: control reaches end of non-void function

Hab a tortan, hogy a clang mintha a -Wreturn-type -re se lenne erzekeny, pedig ebben return aztan egy darab nincsen.
--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal

Nem igazan veszed eszre, hogy a clang csak a main-nel nem szol a return miatt. Ha nincs kiteve akkor odagondolja. A main visszaterese az ot futtato kornyezet szamara fontos es nem a programnak maganak. Ezert felesleges warning-ot dobalni.

Hmmm... persze, amikor nem volt elotte int, akkor meg szolt... bonyolult lelkivilaga van ennek a cuccnak...
--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal

Standardoknak megfeleloen kell kodolni, kodhelyesseget meg nem a forditoval, hanem erre kitalalt lint (es tarsai) programmal ellenorizd.

a) ez nem az en kodom, en is csak ugy talaltam. Meg az algoritmust se igazan ertem, amit hasznal, viszont felettebb alkalmas C fordito tesztelesere. Erre hasznalom.
b) nem celom sem a kod karbantartasa sem a fejlesztese, egyszeruen csak erdekelt a problema
c) nem vagyok hardcore C programozo. Nekem mar az is eleg, ha a C fordito az altalam generalt kodra nem dob errort. Meg jobb, ha warningot sem. Hab a tortan, ha meg mukodik is a kod, ha pedig azt csinalja, amit szeretnek... nos, az szamomra a megtestesult tokely. Ilyen szinten vagyok C-bol.
--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal

a) Nem olyan bonyolult. Az x^2+y^2<=1 az 1 sugarú, 0,0 középpontú "kitöltött" kör* egyenlete. Mivel az x és y csak a [0,1] intervallumon vesz fel értéket (de ott (elvileg) egyenletes eloszlású), ezért annak valószínűsége, hogy a kapott x, y koordináta a körön belülre esik, pi/4. Ha végtelenszer (megfelelően sokszor) növeljük i értékét, ha a kapott koordináta a körön belülre esik, és leosztjuk az iterációk számával (a-val, vagyis s+1-gyel), akkor épp pi/4-et kell, hogy kapjunk, aminek négyszerese pi.

* Ennek a kitöltött körnek mi a precíz, matematikai elnevezése?

korlap, illetve a siknegyedbe eso resze egy korcikk

--
a publikus az egy JOGI fogalom abban az értelmezésben ahogy mi használtuk! nem műszaki. - RockWood1911

Azaz, köszönöm. Nekem a körlemez, illetve angolból a disk ugrott be, de éreztem, hogy egyik sem a megfelelő megnevezés. :)

Szerk: bár a körlemez is használatban van.

@hrgy:
Így talán hasznosabb (a printf-et kivéve a belső ciklusból, és a végére tenni összegezve - idézőjelek nem kellenek, csak formázás miatt van). És akkor itt minél nagyobb a "c" értéke, annál pontosabb lesz a közelítés pi-hez ha jól gondolom:

const c = 100000;

int main() {
    float x,y,i,a=0.0;
    int s;
    for(s=0; s"<"c; s++) {
        x=1.*rand()/RAND_MAX;
        y=1.*rand()/RAND_MAX;
        i+=x*x+y*y<=1;
    }
    printf("%lf\n",4*i/c);
}

(Hogy lehet kiküszöbölni, hogy a code tag-en belüli formázást ne csessze szét a "<" jel?)

sed 's/</\&lt\;/g;s/>/\&gt\;/g'
--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal

ulysses@locris:~/Dev$ clang -Wall -o pi pi.c
pi.c:4:7: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
const c = 10000;
~~~~~ ^
pi.c:7:17: warning: unused variable 'a' [-Wunused-variable]
float x,y,i,a=0.0;
^
2 warnings generated.

:P

int lemaradt, tessék kérem. De azért ez is lefut 20 sec alatt.

Csak tipp, mert tudom, hogy most tanulod a Ruby-t. Az egysoros blokkokhoz felesleges do/end -et hasznalni, oda siman jo a {} is. Egyre azonban figyelj, a {} mint blockwrapper nagyobbb precedenciaju, mint a {} mint hash-wrapper. A ketes esetekben mindig a blokk-definicioe az elsobbseg.

Tehat:

def doIt(options = {}); end

doIt { :foo => :bar } # Hiba
doIt({:foo => :bar}) # OK

Ugyanakkor:

(0..c).each { |i2| i += 1 if rand**2 + rand**2 <= 1 }

--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal

Aha... most eljatszottam a koddal. Sajnos a valszam az nagyon kimaradt az eletembol... de valamit meg mindig nem ertek. Nem mindig pi jon ki a vegere, idonkent egy picit nagyobb szam jon, pl. 3.171 koruliek. Ez miert van?

Valamint ez a valszam resze se tiszta. Azert pi/4 a valoszinusege, hogy a pont a korlapon belul van, mert a kornek negy cikkelyebe eshet, es a korterulet pi? Kozben ezt a reszet megertettem.
--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal

Átírtam C#-ra, futott egy fél délelőttön át, és nálam nagyon szépen konvergál a píhez.

Fuszenecker_Róbert

Nekem igy... fluktual... 3.13 es 3.17 kozott eleg sokmindent felvesz. De lehet, h tenyleg kene hagyni futni :-)
--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal

Persze hogy ingadozik, mivel véletlen bemenetre van alapozva.

Ha a random generátor eloszlása minél nagyobb elemszámot tekintve minél egyenletesebb, annál jobban fog közelíteni az értékhez a hányados. Futtasd le 1 vagy 10 milliószor a ciklust, meg egy srand(time(NULL)) paranccsal inicializáld minden futás előtt a random gen-t. Nagy elemszámnál a tört számlálója és nevezője is nagy lesz, ezért több tizedes jegyig lesz pontos.

Pontosan ugyanezért használtam decimalt C#-ban. A 28-29 értékes tizedesjegy (10-es számrendszerben) jól hangzik. Csak ehhez tényleg 100.000.000 iteráció kell.

Persze ezt a pontosságot nem fogja hozni a program, mert csak véges számú pontot tud "megcímezni" a véletlenszámgenerátor (nem végtelenül finom a felosztás). Szerintem ezért fluktuál neked is, bármennyire állítod az iterációszámot.

Fuszenecker_Róbert

Igazad van, a random generátor felbontása a limit jelenleg.

Jo otlet. Na mindegy, ahhoz kepest, hogy csak C fordito tesztelesehez hasznalom a kodot, jol kiveseztuk :-)
--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal

"nem vagyok hardcore C programozo"
Az latszik, nincs is semmi baj ezzel. Csak akkor meg miert kell hozzaszolni olyan temahoz, amihez fogalmad sincs. Visszaszolni marhasagokat, az mar megy. Inkabb maradtal volna csendben.

Ilyenkor a legjobb jó példával elöljárni.

Mert ez az en blogom, es bocsass meg, de a sajat blogomban ahhoz szolok hozza, amihez akarok mindaddig, amig az az oldal temajaba vag.
--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal

"Meg az algoritmust se igazan ertem, amit hasznal"

nem gondoltam volna, hogy neked ez gondot okozhat

A kor egyenletet ismertem, azt nem igazan ertettem, hogy miert kellett ebbe bevonni a rand()-ot. De most mar kezd oszlani a homaly.
--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal

Monte Carlo

Fuszenecker_Róbert

Ahh, most mar legalabb az elmelet alapjait ertem. Elmes dolog, ez teny. Tenyleg nem hallottam meg errol, nagyon reg foglalkoztam mar matekkal.
--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal

Érdekes, hogy két gcc sem szól. Nálam Windows alatti mingw-s gcc és clang van, emlékeim szerint 4.6.2-es a gcc.

> a clang sirt az a inicializalatlansaga miatt, azt inicializaltam.
:-O

Az eredeti kodhoz kepest valo valtoztatasra ertettem, ott az a sem volt inicializalva.
--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal

dafuq did i just read

--
NetBSD - Simplicity is prerequisite for reliability