Elektroda.pl
Elektroda.pl
X

Wyszukiwarki naszych partnerów

Wyszukaj w ofercie 200 tys. produktów TME
Europejski lider sprzedaży techniki i elektroniki.
Proszę, dodaj wyjątek elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Pierwiastkowanie na 8051

Vinnic 30 Cze 2003 19:04 2195 19
  • #1 30 Cze 2003 19:04
    Vinnic
    Poziom 15  

    Witam.
    Czy ktoś z grupowiczów spotkał się z procedurą obliczenia pierwiastka kwadratowego z liczby 16 bitowej. Interesuje mnie procedura w assemblerze 8051 ewentualnie jakiś sposób (algorytm) tego rozwiązania.

    0 19
  • #3 30 Cze 2003 19:54
    Vinnic
    Poziom 15  

    Dzięki. Tam już byłem

    0
  • #4 01 Lip 2003 13:30
    kubagert
    Poziom 14  

    A znalazles??

    Bo przypomnialo mi sie jeszcze, ze na www.microchip.com sa gdzies opisane rozne rozwiazania mnozenia, dzielenia oraz operacji na liczbach zmiennoprzecinkowych. PIC'e 16 mnozyc nie potrafia, takze czasem jest fajna zabawa jak trzeba pomnozyc liczbe 3bajty*liczba 3 bajty :-)

    Pozdrawiam
    kubagert

    0
  • #5 01 Lip 2003 14:17
    Vinnic
    Poziom 15  

    Dzięki kubagert, ale nie jestem jeszcze zbyt wtajemniczony w programowanie pic'ów. Na stronie micrichip'a cos tam było ale nie na wiele mnie to oświeciło.

    0
  • #6 01 Lip 2003 16:06
    ElGregor
    Poziom 22  

    Napisz jaką potrzebujesz dokładność, jeśli niewielką to najlepiej użyć gotowej tablicy. Jeśli dużej to trzeba rozłożyć funkcję pierwiatkowania np. na szereg Taylora i wtedy obliczać kolejne przybliżenia, ale to wymaga napisania procedur operacji zmiennoprzecinkowych (głownie mnożenie i dodawanie zmiennoprzecinkowe).

    0
  • #7 02 Lip 2003 07:37
    Vinnic
    Poziom 15  

    Dzięki frofme.
    Bardziej interesowałby mnie algorytm z szeregiem Taylora. Nie słyszałem o nim zbyt wiele

    0
  • #8 02 Lip 2003 10:28
    gmp
    Poziom 19  

    Vinnic napisał:
    Witam.
    Czy ktoś z grupowiczów spotkał się z procedurą obliczenia pierwiastka kwadratowego z liczby 16 bitowej. Interesuje mnie procedura w assemblerze 8051 ewentualnie jakiś sposób (algorytm) tego rozwiązania.

    Niech A jest twoja liczba z ktorej szukasz pierwiastka,
    1. Wez dowlon liczbe 8 bitowa powiedzmy X (=128)
    2. Pomnoz ja przez siebie
    3. Porownaj z A
    4a Jesli jest Wieksza to wez liczbe Mnijesz o polowe (=64)
    4b Jesli jest mniejsz to wez wieksza o polowe (=192)
    5 Skok do lini 2 , az do momentu gdy metoda kolejnych przyblizen znjadziesz taka liczbe X ze X*X<A<(X+1)(X+1), dla liczby 16bitowej bedzie to maximum 16 porwnan.

    0
  • #9 26 Lut 2004 09:02
    sLoTeRRR
    Poziom 12  

    Witam wszystkich!

    A jeżeli mam do obliczenia potęgę X do 0.9.
    To wtedy muszę to zamienić na pierwiastek10stopnia z liczby X podniesionej do 9 ?

    Czy jest możliwe zaszyć w ukochanej 51 taki algorytm? Najlepiej w czym znam ASM i C.

    ElGregor napisał:
    to wymaga napisania procedur operacji zmiennoprzecinkowych (głownie mnożenie i dodawanie zmiennoprzecinkowe).


    Czy są już gdzieś gotowe takie procedurki w C lub ASM?
    Jak nie to od czego zacząć? Jak najlepiej skonstruawać taką maszynkę zmiennoprzecinkową. Czym zaznaczać kropkę:). Jak wam najlepiej się to udało.
    Dzięki za pomoc/pozdrawiam

    0
  • #10 26 Lut 2004 11:18
    h-doc
    Poziom 27  

    jesli musisz liczyc potegi o stalym wykladniku, to najlepiej zastosowac metode tablicowa. Ja tak robilem u siebie logarytmowanie - bardzo szybka metoda. Zeby zaoszczedzic na rozmiarze tablicy (a tym samym pamieci), argument wejsciowy przydzielasz do pewnego przedzialu (ktorego szerokosc dobierasz w zaleznosci od pozadanej dokladnosci) a nastepnie na podstawie wyznaczonego przedzialu indeksujesz tablice wartosci funkcji. Do pierwiastkow kwadratowych byl rowniez dosyc prosty algorytm iteracyjny - niestety nie pamietam wzoru.

    0
  • #11 26 Lut 2004 13:27
    ElGregor
    Poziom 22  

    sLoTeRRR napisał:
    Jak nie to od czego zacząć? Jak najlepiej skonstruawać taką maszynkę zmiennoprzecinkową. Czym zaznaczać kropkę:). Jak wam najlepiej się to udało.
    Dzięki za pomoc/pozdrawiam
    Jeżeli nie zależy ci na dużym zakresie, to nie musisz stosować systemu z mantysą, liczby zmiennoprzecinkowe traktujesz jak stałoprzecinkowe.
    Np. 16bitową liczbę można traktować jak 8 bitów przed punktem dziesiętnym i 8 bitów części ułamkowej. Po pomnożeniu przez siebie dwóch takich liczb tak samo jak stałoprzecinowych otrzymujesz 32 bitowy wynik, z czego 16 bitów to część całkowita a pozostałe 16 bitów to część ułamkowa.

    0
  • #12 26 Lut 2004 18:38
    sLoTeRRR
    Poziom 12  

    Dzięki chłopaki!

    A czy jest recepta na to by obliczając pierwiastek z liczby X obojętnie jakiego stopnia, trafić od razu na liczbę Y (obliczoną z liczby X za pomocą jakiegoś algorytmu) która jest pierwiastkiem lub blisko rozwiązania leży?

    Pozdrawiam!

    0
  • #13 26 Lut 2004 19:59
    ElGregor
    Poziom 22  

    sLoTeRRR napisał:
    A czy jest recepta na to by obliczając pierwiastek z liczby X obojętnie jakiego stopnia, trafić od razu na liczbę Y (obliczoną z liczby X za pomocą jakiegoś algorytmu) która jest pierwiastkiem lub blisko rozwiązania leży?
    Tak, trzeba użyć ciągu zbieżnego i w pętli wyliczać kolejne przybliżenia. Dla uzyskania 10 miejsc po przecinku wystarczyć powinno około 8 - 10 przybliżeń. W podobny sposób liczy się na przykład liczbę PI, napisałem kiedyś program liczący do miliona cyfr po przecinku 8)

    0
  • #14 26 Lut 2004 22:57
    sLoTeRRR
    Poziom 12  

    Ludziska Dzięki za pomoc. Na razie mam problemik i pewnie się uśmiejecie:).
    Liczby w sofcie nie przekroczą setki, a po przecinku dwie cyfry.
    Zrobiłem jak zaproponował ElGregor - rozbiłem cyfrę na dwie części. Funkcje dodawania chyba jest. Dodałem najpierw nagłówki dwóch cyfr:) później resztę (po kropce) i podzieliłem przez 100 aby ewentualnie zasilić nagłówek. Nie wiem czy działa ale teoretycznie SPOX. Problem z mnożeniem. Jak najpierw pomnożę nagłówek a później resztę, no to ....wiem, wiem dziecko z przeczkola to wie, że wyjdzie z tego kaszanka. Jak z tej kaszanki uzyskać to co chcem? Znowu pytanko brzmi tylko: Czy istnieje taki algorytm?.
    Bo wpadłem na taki pomysł by mnożyć pisemnie za pomocą algorytmu, ale on jest sttttttttttttrrrrrrrrraaasznie dłuuuuuuuuuuuugi.

    Dla mnie taka matematyka to nowość, to nie protokół transmisjii ani jakaś tam magistrala, to musi być matematyka, a kalkulator trza se zrobić.

    A może jest jakiś Scalaczek do którego puszcza się wartości po 1-wire a on zwraca wynik?

    0
  • #15 27 Lut 2004 02:24
    ElGregor
    Poziom 22  

    sLoTeRRR napisał:
    ...rozbiłem cyfrę na dwie części. Funkcje dodawania chyba jest. Dodałem najpierw nagłówki dwóch cyfr:) później resztę (po kropce) i podzieliłem przez 100 aby ewentualnie zasilić nagłówek.
    Nie masz traktować tej liczby jako dwóch części, po prostu dodajesz części ułamkowe do siebie a potem części całkowite + przeniesienie z części ułamkowej.
    sLoTeRRR napisał:
    Bo wpadłem na taki pomysł by mnożyć pisemnie za pomocą algorytmu, ale on jest sttttttttttttrrrrrrrrraaasznie dłuuuuuuuuuuuugi.
    Użyj klasycznego mnożenia liczb wielobajtowych, kilka mnożeń i kilka dodawań. Jeszcze raz potórzę że taką liczbę ułamkową musisz traktować podczas obliczeń jak całość, jak liczbę naturalną. Przecinek jest tylko umowny.

    0
  • #16 27 Lut 2004 21:22
    sLoTeRRR
    Poziom 12  

    No Jasne! dzięki ElGregor. Rzeczywiście chyba coś mi się pomotało. Jak se coś wmówię to koniec:-). dzięki za wszystko. W sumie to nie jest chyba takie trudne.

    0
  • #17 27 Lut 2004 21:38
    ElGregor
    Poziom 22  

    Rzucę jeszcze mały przykład dla jasności:

    Code:
     C823h
    
    +75B1h
    ------
    13DD4h

    czyli dziesiętnie 51235 + 30129 = 81364

    Analogicznie:
    Code:
     C8,23h
    
    +75,B1h
    ------
    13D,D4h

    czyli dziesiętnie 200,13671875 + 117,69140625 = 317,828125
    Przecinek to tylko sprawa umowna podczas obliczeń, znaczenia nabiera dopiero w procedurach zamieniających na system dziesiętny i odwrotnie.
    Prawda że proste?

    0
  • #18 28 Lut 2004 15:44
    sLoTeRRR
    Poziom 12  

    No!
    Dzięki!
    Rzeczywiście nie takie to trudne:)

    ElGregor napisał:
    Użyj klasycznego mnożenia liczb wielobajtowych, kilka mnożeń i kilka dodawań.

    Klasyczne mnożenie liczb wielobajtowych, może dotyczyć liczb np. czterobajtowych? lub więcej?

    Gdzie o tym mogę poczytać?.
    Czy w trakcie wykonywania operacji wielobajtowych lepiej używać stosu czy rejestrów i przełączać się między bankami?.
    A jeżeli mam wykonać mnożenie na dwóch liczbach 4 bajtowych. Rozdzielamy tą operacje dla ALU na dwie porcje? czy inaczej?

    pozdrawiam!

    0
  • #19 28 Lut 2004 18:24
    ElGregor
    Poziom 22  

    Przy dłuższych liczbach bardziej opłaca się użyć agorytmu z przesuwaniem i dodawaniem a działa on tak (4 bajty x 4 bajty, wynik 8 bajtów):

    Przygotuj 8 bajtowy rejestr komórek w pamięci na wynik, w postaci:
    |Mnozna|00000000h|
    Gdzie 4 starsze bajty to mnożna a cztery młodsze to zera.

    Teraz wykonujesz pętlę 32 razy (4 bajty)
    Przesuwasz 8 bajtowy wynik w lewo, jeśli najstarszy bit jest zerem (skasowany C) to nic nie robisz.
    Jeśli jest jedynką dodajesz do wyniku mnożnik.
    I tak 32 razy. Po zakończeniu pętli masz gotowy wynik mnożenia.

    Code:
    Przykład:
    
    128D9F41h x 8B7C285Dh

    pętla nr.    rejestr wyniku
    1    128D9F41 00000000 - najstarszy bit 0 -> tylko przesuwamy, nic ni e dodajemy
    2    251B3E82 00000000 - tylko shift
    3    4A367D04 00000000 - tylko shift
    4    946CFA08 00000000 - najstarszy bit 1 -> przesuwamy i dodajemy mnożnik
    5    28D9F410 8B7C285D - tylko shift
    6    51B3E821 16F850BA - tylko shift
    7    A367D042 2DF0A174 - shift + dodawanie
    8    46CFA084 E75D6B45 - tylko shift
    9    8D9F4109 CEBAD68A - shift + dodawanie
    10   1B3E8214 28F1D571 - tylko shift
    11   367D0428 51E3AAE2 - tylko shift
    12   6CFA0850 A3C755C4 - tylko shift
    13   D9F410A1 478EAB88 - shift + dodawanie
    14   B3E82143 1A997F6D - shift + dodawanie
    15   67D04286 C0AF2737 - tylko shift
    16   CFA0850D 815E4E6E - shift + dodawanie
    17   9F410A1B 8E38C539 - shift + dodawanie
    18   3E821437 A7EDB2CF - tylko shift
    19   7D04286F 4FDB659E - tylko shift
    20   FA0850DE 9FB6CB3C - shift + dodawanie
    21   F410A1BD CAE9BED5 - shift + dodawanie
    22   E821437C 214FA607 - shift + dodawanie
    23   D04286F8 CE1B746B - shift + dodawanie
    24   A0850DF2 27B31133 - shift + dodawanie
    25   410A1BE4 DAE24AC3 - tylko shift
    26   821437C9 B5C49586 - shift + dodawanie
    27   04286F93 F7055369 - tylko shift
    28   0850DF27 EE0AA6D2 - tylko shift
    29   10A1BE4F DC154DA4 - tylko shift
    30   21437C9F B82A9B48 - tylko shift
    31   4286F93F 70553690 - tylko shift
    32   850DF27E E0AA6D20 - shift + dodawanie

    wynik: A1BE4FE4CD1029Dh

    czyli 128D9F41h x 8B7C285Dh = A1BE4FE4CD1029Dh

    0
  • #20 29 Lut 2004 10:51
    sLoTeRRR
    Poziom 12  

    WOW!
    Dzięki, taki przykład nawet mi się nie śniło otrzymać w prezencie!

    Teraz napisze proga na '51 i na LCD'ku sprawdze czy wyjdzie mi taki wynik:))

    Z dzieleniem i mnożeniem pewnie jest podobnie, ale po takim przykładzie to już sam rusze mózgiem,

    DZIENX! ElGregor!

    0
TME logo Szukaj w ofercie
Zamknij 
Wyszukaj w ofercie 200 tys. produktów TME
TME Logo