Dalsi zahada v C -> Prevod long int na string

Milan B. milan na bastl.sk
Pondělí Červenec 25 00:35:30 CEST 2011


On 24.7.2011 22:38, Jan Waclawek wrote:
> To je sice pekne, ale povodna staznost bola na pomalost. Optimalizacia uz potom nie je zalezitost par minut a je strojovo zavisla.

Aha, takze riesenim je asi vyplakavat po roznych forach.

Dakujem za poucenie.

A kde beriete istotu, ze tieto funkcie - ktore ste mimochodom odporucali 
aj VY SAM - budu v knizniciach implementovane inac? Namatkovo som pozrel 
implementaciu vo vasom oblubenom SDCC a tam je implementovana IMO este 
horsie.

Mimochodom, povodna staznost nebola na rychlost itoa, ale na rychlost 
printf (tuto cast ste rafinovane odmazali). Tazatel sa iba domnieval ze 
algoritmy s delenim budu pomale. Sancu vyskusat itoa a spol. nermal, 
lebo jeho kniznice ich nemaju. Tak som mu nejaku implementaciu ponukol. 
Co vas na tom tak sere?

Ta implementacia samozrejme nie ie najrychlejsia. Na uvod sa da 
odstranit obracanie retazca s tym, ze sa bude zapisovat od konca (ale 
vysledok nebuda zacinat na zaciatku bufra) - a hned je to o par taktov 
rychlejsie.

Alebo mozme uplne odstranit delenie a nahradit ho odpocitanim po radoch 
(obmedzme sa len na desiatkovu sustavu a 16-bitovy integer):

char *utoa(char *s, unsigned n)
{
int cnt, i, j=0;
static t[]={10000u,1000u,100u,10u};

for (i=0; i<4;i++) {
cnt=0;
while(n>=t[i]) {
cnt++;
n-=t[i];
}
if (cnt || j ) {
s[j++]=cnt+'0';
}
}
s[j++]=n+'0';
s[j]=0;
return s;
}

Ak je praca s indexovanymi polami na danej platforme prilis draha, tak 
je mozne cyklus for nahradit styrmi po sebe iducimi cyklami while s 
konstantami (samozrejme, za cenu vyssej spotreby programovej pamate):

char *utoa(char *s, unsigned n)
{

int cnt, i, j=0;

cnt=0;
while(n>=10000u) {
cnt++;
n-=10000u;
}
if (cnt || j) {
s[j++]=cnt+'0';
}
cnt=0;
while(n>=1000u) {
cnt++;
n-=1000u;
}
if (cnt || j) {
s[j++]=cnt+'0';
}
cnt=0;
while(n>=100u) {
cnt++;
n-=100u;
}
if (cnt || j) {
s[j++]=cnt+'0';
}
cnt=0;
while(n>=10u) {
cnt++;
n-=10u;
}
if (cnt || j) {
s[j++]=cnt+'0';
}
s[j++]=n+'0';
s[j]=0;
return s;
}


Neviem, ktore riesenie bude na danej platforme najrychlejsie, zavisi to 
hlavne od rychlosti implementacie delenia. Ale to sa da zistit velmi 
jednoducho - vyskusat.

Len pre zaujimavost, na mojej testovacej x86_64 virtualke (ktora ma, 
samozrejme, HW delenie) trvalo 1000 prevodov celeho rozsahu -32767 az 
32767 (t.j. 65534000 prevodov):

verzia s delenim (a HW delenim): ~2.6 sekundy
verzia s odpocitavanim po radoch s tabulkou: ~4 sekundy
verzia s odpocitavanim po radoch 4 cykly po sebe: ~2.1 sekundy ---> VITAZ

更好吗?

-m-


> wek
>
>
> On Sun, 24 Jul 2011 17:21:27 +0200
> "Milan B."<milan na bastl.sk>  wrote:
>
>> On 24.7.2011 11:37, Michal Gregor wrote:
>>> Tak jsem program upravil na funkce itoa() a utoa().
>>> Kompilator ale hlasi chybu. Tyto funkce nezna.
>> Netreba z toho robit tragediu. Su to jednoduchucke funkcie a a daju sa
>> spichnut za par minut.
>>>> Jan Waclawek konfera na efton.sk
>>>> Úterý Červen 21 14:17:51 CEST 2011
>>>> Neviem ako pri Vasom prekladaci, ale obvykle maju kniznice>k C
>>>> (najma na
>>>> jednocipy) na tento ucel funkciu ltoa() (a>potom aj rozne ito(), ftoa()
>>>> apod.), presne kvoli tomu ze>xxprintf() je nafuknuty a pomaly mamut.
>>>> Ak nie, tak asembler, alebo trpiet pripadnou pomalostou>delenia.
>>>> wek
>>>
>>> ----- Original Message ---------------
>>>> Jak prevadite long int na string? Nasel jsem priklady s delenim, ale
>>>> asi to
>>>> bude taky pekne pomale.
>>>> (Jeste mam havarijni plan zmenit vystupni format na hexa cisla.)
>>>>
> _______________________________________________
> HW-list mailing list  -  sponsored by www.HW.cz
> Hw-list na list.hw.cz
> http://list.hw.cz/mailman/listinfo/hw-list



Další informace o konferenci Hw-list