Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

dziwne zaokrąglanie zmiennej SINGLE - Bascom 1.11.8.7

02 Cze 2007 16:18 3011 2
  • Poziom 12  
    Problem nieprawidłowego zaokrąglania liczb zmiennoprzecinkowych uprościłem i przedstawiam na poniższym przykładzie:

    $regfile = "m8def.dat"
    $crystal = 16000000
    ---------------------------

    Dim Nr As Byte
    Dim Tau_s As Single
    Dim Tau_w As Word

    Cursor Off Noblink '.............ukrycie kursora na LCD
    Cls

    Do
    Restore Tab '...............ustawienie się na pierwszej komórce tablicy Tab
    While Nr < 7 '...............Petla WHILE do tablicy Tab
    Read Tau_s '...............podstawienie do zmiennej Tau_single danego elementu tablicy Tab
    If Tau_s < 0.1 Then '..............sprawdzenie warunku

    Cls
    Lcd "Tau_s=" ; Tau_s

    Tau_w = Tau_s * 10000
    Lowerline
    Lcd "Tau_w=" ; Tau_w

    Else '..............gdy warunek (Tau_s < 1) nie jest spełniony to:
    Cls
    Lcd "Tau_s=" ; Tau_s

    Tau_w = Tau_s * 1000
    Lowerline
    Lcd "Tau_w=" ; Tau_w
    End If

    Waitms 5000
    Wend
    Loop
    End

    Tab:
    Data 0.0010! , 0.233! , 0.0022! , 0.392! , 0.0028! , 0.510! , 0.911!


    Efekt jest taki, że dla przykładu, zamiast czytać z tablicy wpisane wartości SINGLE:
    0.0010 , 0.233 , 0.0022 , itd ...
    to na LCD wypisywane są nieco inne wartości SINGLE, odpowiednio:
    0.00099998 , 0.2329997 , 0.00219994 , itd ...

    O co tu chodzi ??? Dlaczego nie są wyświetlane na LCD dokładnie takie wartości jak wpisane w tablicy?
  • Poziom 19  
    Moim zdaniem spowodowane jest to ograniczona dokladnoscia reprezentacji liczby zmiennoprzecinkowej (sposob obliczania i dlugosc bitowa mantysy liczby). Dosyc dobrze jest to opisane w wikipedii, np. http://pl.wikipedia.org/wiki/Liczba_zmiennoprzecinkowa.

    Z tego samego powodu ja musialem stosowac liczby calkowite w obliczeniach. Przy zachowaniu odpowiednich zasad mozliwe jest w ten sposob wykonywanie obliczen na liczbach nawet do paru cyfr po przecinku z duza dokladnoscia. W takiej sytuacji np. liczbe 1,2345678 zapisujemy jako 12345678, liczbe 0,0301230 jako 301230 itp. Niestety wykonywanie operacji arytmetycznych zmusilo mnie do stosowania 64-bitowego typu long long co sie mocno odbija na zasobach i czasie obliczen.
    Wszystko to odnosi sie do jezyka C i kompilatora avr gcc, bo bascoma nie znam. Dodatkowo na atmedze8 raczej nie zmiescisz kodu generowanego przez kompilator do takich obliczen.
  • Poziom 21  
    Kol. _Matik_ określił przyczynę problemu, ja natomiast chciałem zasugerować rozwiązanie. W Bascomie jest instrukcja ROUND(x). Sądzę, że to jest najprostsze wyjście.