Funkcja pow()

Masz problem, z którym nie możesz sobie poradzić? Pisz śmiało!
ODPOWIEDZ
zgred125
Majsterkowicz
Posty: 88
Rejestracja: 23 gru 2013, 22:39

Funkcja pow()

Post autor: zgred125 » 10 wrz 2014, 00:43

Witam

Potrzebuje funkcję, która do tablicy unsigned long zapisze mi kolejne potęgi liczby 16 tzn 16^0,16^1,16^2,16^3 itd. Jako, że nie wiem ile takich potęg będzie mi potrzebne na szybkości napisałem coś takiego:

Kod: Zaznacz cały

unsigned long potegi[i];
  for (int h=0 ; h<i ; h++)
  {
    potegi[i-h]=pow(16,h);
    Serial.println(potegi[i-h]);
  }
Zmienna "i" w kodzie określa jak wiele elementów będzie miała moja tablica oraz do jak dużej potęgi będę podnosił liczbę 16.

Wszystko wydaje mi się logiczne ale efektem działania powyższego kodu jest:

Kod: Zaznacz cały

1 // niby ok
15 // powinno być 16
255 // powinno być 256
4095 // powinno być 4096
65535// idt...
1048574
16777194
268435104 // a to powinno być 268435456
Ma ktoś pomysł skąd się bierze powyższy błąd??

Co miesiąc do wygrania nagrody o wartości ponad 1600 zł!


Awatar użytkownika
djbuh
Majsterkowicz
Posty: 232
Rejestracja: 9 gru 2012, 19:45
Lokalizacja: Bytom
Kontakt:

Re: Funkcja pow()

Post autor: djbuh » 10 wrz 2014, 01:58

Spróbuj samemu napisać odpowiednik funkcji pow(), czyli w pętli for mnożyć 16 przez siebie samą i po każdej operacji zapisywać ją do kolejnej pozycji tablicy. Może problem tkwi w zastosowanej funkcji. Znajdź sobie jej dokumentację, pewnie tam jest wyjaśnione dokładne jej działanie oraz to co można, a czego nie można robić. Możliwe, że źle jej używasz.
stiven
Złota rączka
Posty: 1581
Rejestracja: 13 maja 2014, 08:47
Lokalizacja: Zielona Góra

Re: Funkcja pow()

Post autor: stiven » 10 wrz 2014, 11:59

Dziwne to, bo funkcja pow() jest dobrze użyta. Ale jest inny błąd, który nie powinien mieć wpływu na obliczenia.
W różnych językach programowania bywa różnie z tablicami, w C jest tak, że taki na przykład zapis

Kod: Zaznacz cały

unsigned long potegi[5];

oznacza deklarację tablicy pięcioelementowej i może się to wydać dziwne, ale w programie NIE MOŻNA napisać na przykład

Kod: Zaznacz cały

potegi[5] = pow(16, 1)
Wynika to z tego, że tablica ma 5 pól, ale zawsze liczy się je od 0, czyli w tym przypadku od 0 do 4. Kiedy w programie h jest równe 0, to zapis nie jest do ostatniego elementu tablicy, tylko już poza tablicę, jak się tam w pętli napisze potegi[i-h-1], to będzie się wszystko zgadzać.
Ciekawe jest to, że nawet jak się zrobi taką pomyłkę, to i tak najczęściej jest dobrze. Można nawet zapisywać i odczytywać jeszcze dalej, potegi[6], potegi[7], potegi[29] i też może być dobrze. To jest tak z tymi tablicami, że deklarując tablicę, deklaruje się jej początek w pamięci, wskaźnik do pierwszego pola (czyli tego zerowego), kolejne pola tablicy w pamięci są "wyznaczane" ze wskaźnika plus typu danych. Ale z takim niewłaściwym wykorzystaniem tablic wiąże się niebezpieczeństwo błędów w działaniu programu. Program w trakcie uruchamiania się alokuje pamięć dla wszystkich zmiennych. Dla tablicy zastrzeżony w pamięci będzie tylko ten właściwy obszar, a zapisując za tablicę, może się okazać, że tam ma miejsce inna zmienna i wtedy nadpiszemy ją. W jednym uruchomieniu może być wszystko w porządku, ale w kolejnym inaczej pamięć będzie zaalokowana i mogą być już błędy. Tak to jest "zorganizowane" i trzeba tego samemu pilnować.
zgred125
Majsterkowicz
Posty: 88
Rejestracja: 23 gru 2013, 22:39

Re: Funkcja pow()

Post autor: zgred125 » 10 wrz 2014, 13:35

Dziękuje Stiven faktycznie głupi błąd, "macanie" poza tablica mogło spowodować różne błędy ale ten akurat wynika z czego innego. Poniższa pętla już jest poprawna int h zawsze będzie mniejszy o 1 od ilości elementów w tablicy. Problem jednak pozostał:

Kod: Zaznacz cały

unsigned long potegi[i];
  for (int h=0 ; h<i ; h++)
  {
    potegi[h]=pow(16,h);
    Serial.println(potegi[h]);
  }

Kod: Zaznacz cały

1
15
255
4095
65535
1048574
16777194
268435104
zgred125
Majsterkowicz
Posty: 88
Rejestracja: 23 gru 2013, 22:39

Re: Funkcja pow()

Post autor: zgred125 » 11 wrz 2014, 20:07

Nie udało Mi się dość dlaczego się tak dzieje, zdecydowałem się napisać własną funkcję do potęgowania. Dla potomnych może komuś się przyda:

Kod: Zaznacz cały

unsigned long poteguj(int wykladnik, int podstawa)
{
  unsigned long liczba=1;
  for (int i=0 ; i<=wykladnik; i++)
  {
    liczba*=podstawa;
  }
  return (liczba);
}
Funkcje wywołujemy poprzez jej nazwę. A w argumentach przekazujemy wykładnik i podstawę np:

Kod: Zaznacz cały

int x; //- wykladnij
int y; //- podstawa
a=poteguj(x,y)
ODPOWIEDZ

Strony partnerskie: