Kezdőlap › Fórumok › Programozás › Forráskód nem hordozható?
- This topic has 80 hozzászólás, 9 résztvevő, and was last updated 16 years, 7 months telt el by
uzsolt.
-
SzerzőBejegyzés
-
2008-12-13-21:12 #2177718
A C forráskód hordozható, semmi gond vele. Viszont a lebegőpontos ábrázolás és aritmetika nem éppen könnyű, bármennyire is annak látszik. Elég ha túl kicsi számmal történik osztás, és ott is a NaN, azt meg már hiába kisebbíted. Egyes processzorok több bittel ábrázolják a számokat a lebegőpontos regiszterekben mint ahogy tárolják, ezt a -ffloat-store opcióval tudod kiküszöbölni. Aztán ott van a véges ábrázolás miatti hiba elhanyagolása, amikor azt feltételezed, hogy két szám egyenlő, és nem azt hogy a két szám különbsége kisebb egy hibamaximumnál (lásd hibaterjedés). Egyes véges decimális számokat nem lehet hiba nélkül véges bináris lebegőpontos formában ábrázolni, más részeredmények meg végesek lehetnek tört formában, de véges lebegőpontos alakban nem, stb…
Egy példa, hogy milyen könnyű látszólag jó, de valójában hibás kódot írni:
Code:#includeint main ()
{
double a, b;
float m;
b = a = 1.0;
m = 1.0 / 3.0;
a -= m * 3.0;
a += 1.0;
if (a == b)
printf(„Egyenlőn”);
else
printf(„Nem egyenlő: %lf, %lfn”, a, b);
}Eredmény (nem meglepő módon):
Code:Nem egyenlő: 1.000000, 1.0000002008-12-13-21:12 #2177719A C forráskód hordozható, semmi gond vele. Viszont a lebegőpontos ábrázolás és aritmetika nem éppen könnyű, bármennyire is annak látszik. Elég ha túl kicsi számmal történik osztás, és ott is a NaN, azt meg már hiába kisebbíted. Egyes processzorok több bittel ábrázolják a számokat a lebegőpontos regiszterekben mint ahogy tárolják, ezt a -ffloat-store opcióval tudod kiküszöbölni. Aztán ott van a véges ábrázolás miatti hiba elhanyagolása, amikor azt feltételezed, hogy két szám egyenlő, és nem azt hogy a két szám különbsége kisebb egy hibamaximumnál (lásd hibaterjedés). Egyes véges decimális számokat nem lehet hiba nélkül véges bináris lebegőpontos formában ábrázolni, más részeredmények meg végesek lehetnek tört formában, de véges lebegőpontos alakban nem, stb…
Egy példa, hogy milyen könnyű látszólag jó, de valójában hibás kódot írni:
Code:#includeint main ()
{
double a, b;
float m;
b = a = 1.0;
m = 1.0 / 3.0;
a -= m * 3.0;
a += 1.0;
if (a == b)
printf(„Egyenlőn”);
else
printf(„Nem egyenlő: %lf, %lfn”, a, b);
}Eredmény (nem meglepő módon):
Code:Nem egyenlő: 1.000000, 1.0000002008-12-13-21:21 #2177720Binárist nem próbáltad hurcolni?
2008-12-13-21:21 #2177721Binárist nem próbáltad hurcolni?
2008-12-13-21:24 #2177722gabaman wrote:Elég ha túl kicsi számmal történik osztás, és ott is a NaN, azt meg már hiába kisebbíted. Egyes processzorok több bittel ábrázolják a számokat a lebegőpontos regiszterekben mint ahogy tárolják, ezt a -ffloat-store opcióval tudod kiküszöbölni.Akkor azt mondod/gondolod, hogy a -ffloat-store lehet a megoldás? Ha esetleg van néhány unalmas perced, vetnél a progira egy-két pillantást? /Cikizni nem kell 😉 /
Az „egyenlő, de mégse egyenlő” jelenségről tudok, ilyenkor egy kicsi epsilont szoktam használni (abs(a-b)<eps), de gondolom most nem ez a probléma gyökere.
Wait wrote:Binárist nem próbáltad hurcolni?Dehogynem. Azzal kaptam először a nan-okat, aztán mondom, fordítsuk le, ott is ugyanaz volt a helyzet.
2008-12-13-21:24 #2177723gabaman wrote:Elég ha túl kicsi számmal történik osztás, és ott is a NaN, azt meg már hiába kisebbíted. Egyes processzorok több bittel ábrázolják a számokat a lebegőpontos regiszterekben mint ahogy tárolják, ezt a -ffloat-store opcióval tudod kiküszöbölni.Akkor azt mondod/gondolod, hogy a -ffloat-store lehet a megoldás? Ha esetleg van néhány unalmas perced, vetnél a progira egy-két pillantást? /Cikizni nem kell 😉 /
Az „egyenlő, de mégse egyenlő” jelenségről tudok, ilyenkor egy kicsi epsilont szoktam használni (abs(a-b)<eps), de gondolom most nem ez a probléma gyökere.
Wait wrote:Binárist nem próbáltad hurcolni?Dehogynem. Azzal kaptam először a nan-okat, aztán mondom, fordítsuk le, ott is ugyanaz volt a helyzet.
2008-12-13-22:11 #2177724uzsolt wrote:vetnél a progira egy-két pillantást? /Cikizni nem kell 😉 /Akkor „no comment” módban:
Code:==26995== Memcheck, a memory error detector.
==26995== Copyright (C) 2002-2007, and GNU GPL’d, by Julian Seward et al.
==26995== Using LibVEX rev 1804, a library for dynamic binary translation.
==26995== Copyright (C) 2004-2007, and GNU GPL’d, by OpenWorks LLP.
==26995== Using valgrind-3.3.0, a dynamic binary instrumentation framework.
==26995== Copyright (C) 2000-2007, and GNU GPL’d, by Julian Seward et al.
==26995== For more details, rerun with: -v
==26995==
==26995== My PID = 26995, parent PID = 26994. Prog and args are:
==26995== ./csillag
==26995==
==26995== Conditional jump or move depends on uninitialised value(s)
==26995== at 0x8048872: force (csillag.c:108)
==26995== by 0x80489DD: g (csillag.c:151)
==26995== by 0x8049045: rk4 (csillag.c:268)
==26995== by 0x8049554: main (csillag.c:370)
==26995==
==26995== Conditional jump or move depends on uninitialised value(s)
==26995== at 0x8048874: force (csillag.c:108)
==26995== by 0x80489DD: g (csillag.c:151)
==26995== by 0x8049045: rk4 (csillag.c:268)
==26995== by 0x8049554: main (csillag.c:370)
==26995==
==26995== Conditional jump or move depends on uninitialised value(s)
==26995== at 0x8048918: force (csillag.c:118)
==26995== by 0x80489DD: g (csillag.c:151)
==26995== by 0x8049045: rk4 (csillag.c:268)
==26995== by 0x8049554: main (csillag.c:370)
==26995==
==26995== Conditional jump or move depends on uninitialised value(s)
==26995== at 0x804891A: force (csillag.c:118)
==26995== by 0x80489DD: g (csillag.c:151)
==26995== by 0x8049045: rk4 (csillag.c:268)
==26995== by 0x8049554: main (csillag.c:370)
==26995==
==26995== Conditional jump or move depends on uninitialised value(s)
==26995== at 0x43B857: __printf_fp (in /lib/libc-2.6.so)
==26995== by 0x4370CC: vfprintf (in /lib/libc-2.6.so)
==26995== by 0x440022: printf (in /lib/libc-2.6.so)
==26995== by 0x80495A8: main (csillag.c:374)
==26995==
==26995== Conditional jump or move depends on uninitialised value(s)
==26995== at 0x43B8D7: __printf_fp (in /lib/libc-2.6.so)
==26995== by 0x4370CC: vfprintf (in /lib/libc-2.6.so)
==26995== by 0x440022: printf (in /lib/libc-2.6.so)
==26995== by 0x80495A8: main (csillag.c:374)
==26995==2008-12-13-22:11 #2177725uzsolt wrote:vetnél a progira egy-két pillantást? /Cikizni nem kell 😉 /Akkor „no comment” módban:
Code:==26995== Memcheck, a memory error detector.
==26995== Copyright (C) 2002-2007, and GNU GPL’d, by Julian Seward et al.
==26995== Using LibVEX rev 1804, a library for dynamic binary translation.
==26995== Copyright (C) 2004-2007, and GNU GPL’d, by OpenWorks LLP.
==26995== Using valgrind-3.3.0, a dynamic binary instrumentation framework.
==26995== Copyright (C) 2000-2007, and GNU GPL’d, by Julian Seward et al.
==26995== For more details, rerun with: -v
==26995==
==26995== My PID = 26995, parent PID = 26994. Prog and args are:
==26995== ./csillag
==26995==
==26995== Conditional jump or move depends on uninitialised value(s)
==26995== at 0x8048872: force (csillag.c:108)
==26995== by 0x80489DD: g (csillag.c:151)
==26995== by 0x8049045: rk4 (csillag.c:268)
==26995== by 0x8049554: main (csillag.c:370)
==26995==
==26995== Conditional jump or move depends on uninitialised value(s)
==26995== at 0x8048874: force (csillag.c:108)
==26995== by 0x80489DD: g (csillag.c:151)
==26995== by 0x8049045: rk4 (csillag.c:268)
==26995== by 0x8049554: main (csillag.c:370)
==26995==
==26995== Conditional jump or move depends on uninitialised value(s)
==26995== at 0x8048918: force (csillag.c:118)
==26995== by 0x80489DD: g (csillag.c:151)
==26995== by 0x8049045: rk4 (csillag.c:268)
==26995== by 0x8049554: main (csillag.c:370)
==26995==
==26995== Conditional jump or move depends on uninitialised value(s)
==26995== at 0x804891A: force (csillag.c:118)
==26995== by 0x80489DD: g (csillag.c:151)
==26995== by 0x8049045: rk4 (csillag.c:268)
==26995== by 0x8049554: main (csillag.c:370)
==26995==
==26995== Conditional jump or move depends on uninitialised value(s)
==26995== at 0x43B857: __printf_fp (in /lib/libc-2.6.so)
==26995== by 0x4370CC: vfprintf (in /lib/libc-2.6.so)
==26995== by 0x440022: printf (in /lib/libc-2.6.so)
==26995== by 0x80495A8: main (csillag.c:374)
==26995==
==26995== Conditional jump or move depends on uninitialised value(s)
==26995== at 0x43B8D7: __printf_fp (in /lib/libc-2.6.so)
==26995== by 0x4370CC: vfprintf (in /lib/libc-2.6.so)
==26995== by 0x440022: printf (in /lib/libc-2.6.so)
==26995== by 0x80495A8: main (csillag.c:374)
==26995==2008-12-13-22:23 #2177726Most vagy én vagyok hülye, vagy csak szimplán nem értem: a 108. és 118. sorban nem inicializált változót használ? Ha a forráskódot nézem (103-114. sor):
[red]tmp=0;[/red]
for (k=0; k<DIM; k++) {
tmp+=sq(r[k]);
}
// Ha a két bolygó egy pontban van, akkor hibát jelzünk, és NULL-t adunk vissza
if (tmp == 0) {
char *errstr = malloc(50);
sprintf(errstr,”%d. és %d. bolygó összeütközött!”,i,j);
error(errstr);
free(errstr);
return NULL;
}Vagy inkább az kellene az if-be, hogy (tmp<1E-6) és nem (tmp==0) /mondjuk/?
2008-12-13-22:23 #2177727Most vagy én vagyok hülye, vagy csak szimplán nem értem: a 108. és 118. sorban nem inicializált változót használ? Ha a forráskódot nézem (103-114. sor):
[red]tmp=0;[/red]
for (k=0; k<DIM; k++) {
tmp+=sq(r[k]);
}
// Ha a két bolygó egy pontban van, akkor hibát jelzünk, és NULL-t adunk vissza
if (tmp == 0) {
char *errstr = malloc(50);
sprintf(errstr,”%d. és %d. bolygó összeütközött!”,i,j);
error(errstr);
free(errstr);
return NULL;
}Vagy inkább az kellene az if-be, hogy (tmp<1E-6) és nem (tmp==0) /mondjuk/?
-
SzerzőBejegyzés
- Be kell jelentkezni a hozzászóláshoz.
legutóbbi hsz