Jeste jeden C kviz na nedelni vecer

Jan Waclawek konfera na efton.sk
Pondělí Září 20 00:37:40 CEST 2010


Je to pi, a je to velmi pekne - nie je to nahodou z OCCC?.

Pointa je, ze tomu kruhu sa moze zvacsit priemer (pri zachovani jeho "struktury) a bude to stale ratat dobre.

Rata to totiz plochu (v premennej F) a priemer (v premennej OO). Kedze plocha je pi*d*d/4, t.j. F=pi*OO*OO/4, ten vyraz v printf (4.*-F/OO/OO) je vlastne "otocenim" tohoto vztahu, a vysledkom je pi (v tejto verzii je F=-202 a OO=-16).

Ako prve je treba si ten program poriadne pozriet, lebo v duchu OCCC sa pouzivaju zamerne podobne vyzerajuce retazce. Je tam premenna OO (dvakrat velke O), inicializacna hodnota 00 (dve nuly, to v C je nula v osmickovom zapise ;-) ) a funkcia F_OO(), ktora je volana hned na zaciatku main(), je definovana hned za main() a je to vlastne len ta "gula".

No a "gula" funguje na zaklade expanzie makra, ktoreho meno je _ (podciarnik), a medzi nimi su tie minuska. Ten vyraz z makra je ukonceny bodkociarkou, takze to minusko funguje ako obratenie znamienka F. Este poznamenajme, ze F (aj OO, len tam to nie je dolezite) je inicializovany na nulu a potom sa len dekrementuje, cely cas hned po prvom dekremente je zaporne.

Vyraz z makra:
F-->00 || F-OO--;

je logicky OR, ktoreho vysledok je zahadzovany (nie je nijako pouzity - to v C je v poriadku). Dovod je tu ten, ze u logickych operatoroch sa v C nevyhodnocuje druhy vyraz, ak je z prveho vyrazu jasny vysledok. Este treba vediet, ze v C znamena F-- postdekrement, t.j. sa najprv pouzije hodnota vyrazu F a potom sa dekrementuje. Ten druhy podvyraz je len take klamanie telom: vypocita sa F-OO ale vysledok sa zahodi, no a potom sa urobi ten postdekrement OO.

Takze ten vyraz sa da prepisat do ludskej reci ako

if (F > 0) { 
  // tu je uz jasne, ze vysledok log.OR = 1, takze sa nic ine nerobi
  // lenze F je nula alebo zaporne, takze sem sa program na zaciatku riadku nedostane 
} else {
  OO = OO -1;
}
F = F - 1;

Lenze hned druha expanzia makra v tom riadku (a aj vsetky dalsie) ma uz pred sebou to minus, ktore sa uplatni na F v tej uvodnej podmienke, takze uz sa v dalsich "instanciach" makra v danom riadku prechadza prvou vetvou toho "if" a nie druhou, t.j. sa uz OO nedekrementuje.

A preto OO sa dekrementuje len raz v kazdom riadku, a F sa dekrementuje raz pre kazdy vyskyt _.

Pekne, ze? (teda aspon v tak zvratenom slova zmysle ako je C samotne zvratene...) ;-)

wek


On Sun, 19 Sep 2010 22:54:26 +0200
Tomáš Dresler <dresler at hw.cz> wrote:

> Vzpominam-li dobře, není to PI?
> 
> Tomas
> 
> -----Original Message-----
> From: hw-list-bounces at list.hw.cz [mailto:hw-list-bounces at list.hw.cz] On
> Behalf Of Pavel Troller
> Sent: Sunday, September 19, 2010 9:32 PM
> To: HW-news
> Subject: OT: Jeste jeden C kviz na nedelni vecer
> 
> 
> Zdravim,
>   tak schvalne, kdo prijde na to, co priblizne vypocita tento program
> a jaky je jeho algoritmus :-).
>   Pavel
> 
> #include <stdio.h>
> #define _ F-->00 || F-OO--;
> long F=00,OO=00;
> main(){F_OO();printf("%1.3f\n", 4.*-F/OO/OO);}F_OO()
> {
>             _-_-_-_
>        _-_-_-_-_-_-_-_-_
>     _-_-_-_-_-_-_-_-_-_-_-_
>   _-_-_-_-_-_-_-_-_-_-_-_-_-_
>  _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
>  _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
> _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
> _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
> _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
> _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
>  _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
>  _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
>   _-_-_-_-_-_-_-_-_-_-_-_-_-_
>     _-_-_-_-_-_-_-_-_-_-_-_
>        _-_-_-_-_-_-_-_-_
>             _-_-_-_
> }


Další informace o konferenci Hw-list