Forráskód nem hordozható?

Kezdőlap Fórumok Programozás Forráskód nem hordozható?

10 bejegyzés megtekintése - 1-10 / 81
  • Szerző
    Bejegyzés
  • #2177718
    gabaman
    Felhasználó

      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:
      #include

      int 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.000000
      #2177719
      gabaman
      Felhasználó

        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:
        #include

        int 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.000000
        #2177720
        Wait
        Felhasználó

          Binárist nem próbáltad hurcolni?

          #2177721
          Wait
          Felhasználó

            Binárist nem próbáltad hurcolni?

            #2177722
            uzsolt
            Felhasználó
              gabaman 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.

              #2177723
              uzsolt
              Felhasználó
                gabaman 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.

                #2177724
                gabaman
                Felhasználó
                  uzsolt 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==
                  #2177725
                  gabaman
                  Felhasználó
                    uzsolt 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==
                    #2177726
                    uzsolt
                    Felhasználó

                      Most 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/?

                      #2177727
                      uzsolt
                      Felhasználó

                        Most 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/?

                      10 bejegyzés megtekintése - 1-10 / 81
                      • Be kell jelentkezni a hozzászóláshoz.