Błąd w kodzie (obliczanie potęgi)

0

Mam takie zadanie:

Plik: potega.c

Uruchamianie: ./potega <podstawa> <potega>

Treść: Napisz program, który pobiera z linii poleceń dwie liczby całkowite: ‘podstawę’ i ‘potęgę’. Następnie program, wykorzystując pętlę ‘for’, oblicza wartość ‘podstawa’ do potęgi ‘potęga’ i wypisuje na ekran wynik.

Wyjście:

./potega 2 5
2 ^ 5 = 32

Napisałam taki program:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
    if(argc != 3){
        printf("Nieprawidlowa liczba danych");
        return 0;
    }
    int podstawa = atoi(argv[1]);
    int potega = atoi(argv[2]);
    if(potega == 0){
        printf("%s ^ %s = 1", argv[1], argv[2]);
        return 0;
    }
    int wynik = podstawa;
    for(int i=0; i<potega-1; i++){
        wynik = wynik*podstawa;
        }
    printf("%s ^ %s = %d", argv[1], argv[2], wynik);
    return 0;
}

gdzieś jednak jest błąd, bo przy małych liczbach liczy wszystko dobrze, ale przy większych daje dziwne wyniki, a nawet czasem ujemne (czego już kompletnie nie rozumiem xD). Co jest nie tak?

2

Pewnie nic — podaj przykład tych danych, dla których wychodzą złe wyniki, bo zapewne po prostu Ci się zmienna przekręca.

0

@Althorion: np: 10^10 albo 8^12

1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
    if(argc != 3)
    {
        printf("Nieprawidlowa liczba danych");
        return 0;
    }
    long long podstawa=atoll(argv[1]), potega=atoll(argv[2]), wynik=1;
    for(long long i=0;i<potega;++i) wynik*=podstawa;
    printf("%lld ^ %lld = %lld",podstawa,potega,wynik);
    return 0;
}
4

np: 10^10 albo 8^12

No to tak jak mówiłem. 10^10 > 2^33 > 2^31 - 1, i podobnie z 8^12 = 2^36 > 2^31 - 1. unsigned long long na typowych architekturach da Ci 64 bity dokładności, więc pozwoli trzymać liczby do 2^64 - 1, a jak chcesz więcej, to albo bierzesz gotowca typu GMP, albo klepiesz coś swojego  —  najprostsza implementacja to wektor cyfr i działania wykonywane „pisemnie”.

1
Sway22 napisał(a):

gdzieś jednak jest błąd, bo przy małych liczbach liczy wszystko dobrze, ale przy większych daje dziwne wyniki, a nawet czasem ujemne (czego już kompletnie nie rozumiem xD). Co jest nie tak?

Wszystko w porządku. Właśnie odblokowałaś achievement pod tytułem jak są trzymane liczby całkowite w komputerze. Czyli to, że ci nie działa, to akurat dobrze, bo robisz postęp. Gdyby ci wszystko działało, to byś nauczyła się mniej, bo tylko robienia pętli i ifów.

Ogólnie liczby całkowite są trzymane w postaci zero-jedynkowej w ten sposób, że mają swój określony rozmiar (np. 32 bity, 64 bity itp.). To oznacza, że nie zapiszesz liczb zbyt dużych, które się nie zmieszczą w bitach. Wtedy nastąpi przepełnienie i liczba leci od nowa.
Np.

unsigned char a = 255 + 10;
printf("liczba: %d", a); // liczba: 9

ponieważ unsigned char ma tylko 8 bitów bez znaku (liczby od 0 do 255), to nie może tam być zapisana liczba 265, bo następuje przepełnienie i zostaje zapisana tylko reszta (9). Niektóre języki (np. Rust) nie pozwolą nawet na taką operację i zgłoszą błąd.

Natomiast biorąc pod uwagę sposób, w jaki są zapisywane liczby ujemne, to masz odpowiedź dlaczego duże liczby przechodzą w ujemne.

1 użytkowników online, w tym zalogowanych: 0, gości: 1