Beli Temat założony przez niniejszego użytkownika |
Kalkulator dużych liczb całkowitych » 2016-12-27 12:31:56 Mam problem z projektem zaliczeniowym w języku C. Chodzi o kalkulator dwóch dowolnych liczb całkowitych (dodawanie, odejmowanie, mnożenie i dzielenie), ale tylko tych 32-cyfrowych. Radzę sobie jak na razie raczej kiepsko i już samo dodawanie sprawiło mi kłopot. Nie wiem czy istnieje jakaś sprytna metoda z wykorzystaniem stosów na to zadanie, w każdym razie ja starałem się naśladować dodawanie pod kreską. #include <stdio.h> #include <stdlib.h>
int Dodawanie( char X[], char Y[], char Z[] ) { int i, suma; int p = 0; for( i = 31; i >= 0; i-- ) { suma = X[ i ] + Y[ i ] + p; Z[ i ] = suma % 10; p = suma / 10; } return p; } int main() { int i; printf( "Podaj pierwsza liczbe 32-cyfrowa: \n" ); char A[ 32 ]; scanf( "%s", A ); printf( "Twoja liczba to: " ) for( i = 0; i < 32; i++ ) printf( "%d", A[ i ] - 48 ); printf( "\nPodaj druga liczbe 32-cyfrowa: \n" ); char B[ 32 ]; scanf( "%s", B ); printf( "Twoja liczba to: " ) for( i = 0; i < 32; i++ ) printf( "%d", B[ i ] - 48 ); printf( "\n" ); char C[ 33 ]; for( i = 0; i <= 32; i++ ) C[ i ] = 0; Dodawanie( A, B, C ); for( i = 31; i >= 0; i-- ) printf( "%d", C[ i ] ); return 0; }
Jak na razie chodzi mi tylko o to, co robię nie tak (a jestem pewien że całkiem sporo), że wynik wychodzi kompletnie inny niż powinien. Odejmowaniem, mnożeniem i dzieleniem zajmę się później, jakimś interfejsem tak samo - podejrzewam że w kilku miejscach w podprogramie Dodawanie mogłem po prostu pomylić int z charem, tudzież nie zastosować wskaźników, ale nie czuję tego i nie potrafię samodzielnie wyłapać. Nie jestem też pewien jak uwzględnić sytuację, gdy wynikiem dodawania będzie liczba 33-cyfrowa, a że chodzi o liczby całkowite, a nie naturalne, to dochodzi jeszcze problem z wynikami ujemnymi, no i przez to zaczynam się zastanawiać patrząc na te moje wypociny czy nie proszę Was tutaj o reanimację trupa :D |
|
mateczek |
» 2016-12-27 12:54:11 sprytny istnieje. biblioteka gmp :) https://www.youtube.com/watch?v=Mr6yAf9XpE0&t=3s
A błędów szukaj debuggerem |
|
latajacaryba |
» 2016-12-27 12:58:09 Tablica C chyba nie jest pusta (nie wypełniona zerami) weź wszystko w komentarz i wyświetl samą tablicę C, to zobaczysz co wyjdzie. To pewnie to psuje wynik |
|
mateczek |
» 2016-12-27 13:20:09 W C u mnie kiepsko. 1 Ale błąd masz ewidentny licząc cyfrę z tablicy char !!!! 2 Drugi błąd to wydaje mi sie, że zakładasz iż obie liczby mają stałą długość i w dodatku równą . Liczbę po wczytaniu do tablicy musiał byś wyrównać do prawej strony tej tablicy. I dopiero potem dodawać w sposób, który sobie wybrałeś #include <iostream> using namespace std;
string Dodawanie( string X, string Y ) { int p = 0; string wynik; int indexX = X.size() - 1; int indexY = Y.size() - 1; int _x, _y; while(( indexX >= 0 ) ||( indexY >= 0 ) ||( p > 0 ) ) { if( indexX >= 0 ) { _x = X[ indexX-- ] - '0'; } else _x = 0; if( indexY >= 0 ) { _y = Y[ indexY-- ] - '0'; } else _y = 0; int suma = p + _x + _y; int cyfra = suma % 10; p = suma / 10; wynik.insert( wynik.begin(), cyfra + '0' ); } return wynik; } int main() { string l1 { "1232" }; string l2 { "121" }; string w = Dodawanie( l1, l2 ); cout << w; } |
|
Beli Temat założony przez niniejszego użytkownika |
» 2016-12-27 14:16:17 Nie jestem pewien czy biblioteka gmp przejdzie - prowadzący zakłada że program musi się przynajmniej skompilować, jeśli uda mi się ją jakoś zaimplementować u siebie będzie ona również działała u niego przy sprawdzaniu?
@latajacaryba - zrobiłem tak jak pisałeś, rzeczywiście nie była wyzerowana. Uzupełniłem to w kodzie u góry, mam nadzieję że dobrze, ale nadal wyniki nie są poprawne, więc musiałem pomylić się jeszcze gdzieś. @mateczek - nie bardzo rozumiem, w którym konkretnie miejscu popełniam błąd licząc cyfrę z tabeli char? W mainie, w podprogramie? A co do długości liczb - nie wiem czy dobrze rozumiem, ale wg polecenia tak chyba właśnie jest, obie liczby mają stałą i równą długość, są 32-cyfrowe - to chyba takie ułatwienie ze strony prowadzącego. |
|
mateczek |
» 2016-12-27 14:28:25 suma = X[ i ] + Y[ i ] + p;
_x = X[ i ] - '0'; _y = Y[ i ] - '0'; int suma = p + _x + _y;
char A[ 32 ]; //tablica powinna uwzględniać miejsce na terminator C-stringa czyli powinna być o jeden większa od oczekiwanej długości łańcucha!!! i zdecyduj się czy robisz na liczbach czy na znakach !!! //edit powinno być jakoś tak rozmiar dałem na 5; #include <stdio.h> #include <stdlib.h>
int Dodawanie( char X[], char Y[], char Z[], int size ) { int i, suma; int p = 0; Z[ size + 1 ] = '\0'; for( i = size - 1; i >= 0; i-- ) { suma = X[ i ] - '0' + Y[ i ] - '0' + p; Z[ i + 1 ] = suma % 10 + '0'; p = suma / 10; } Z[ 0 ] = p + '0'; return p; } int main() { const int size = 5; char A[ size + 1 ] { "99999" }; char B[ size + 1 ] { "11111" }; char C[ size + 2 ]; Dodawanie( A, B, C, 5 ); printf( "%s,", C ); return 0; }
|
|
mokrowski |
» 2016-12-27 23:29:42 Masz i baw się... jakoś w tym stylu bym to popełnił... #include <stdio.h> #include <string.h> #include <ctype.h> #include <stdlib.h>
#define MAX_POSITIONS 32
void read_value_string( char * values_s ) { printf( "Podaj %u pozycyjną liczbę dodatnią całkowitą: ", MAX_POSITIONS ); scanf( " %" MAX_POSITIONS "s", values_s ); }
void convert_string_to_values( char const * values_s, unsigned * values_u ) { size_t string_length = strlen( values_s ); size_t offset = MAX_POSITIONS - string_length - 1; for( size_t i = string_length; i != 0; --i ) { char letter = values_s[ i - 1 ]; if( !isdigit( letter ) ) { fprintf( stderr, "Znak '%c' na pozycji %zu nie jest cyfrą.\n", letter, i ); exit( EXIT_FAILURE ); } values_u[ offset + i ] =( unsigned )( letter - '0' ); } }
void add_values( unsigned * src1, unsigned * src2, unsigned * dst ) { unsigned carry = 0; unsigned sum; for( size_t i = MAX_POSITIONS; i != 0; --i ) { sum = src1[ i - 1 ] + src2[ i - 1 ] + carry; carry = sum / 10; sum %= 10; dst[ i ] = sum; } dst[ 0 ] = carry; }
char * convert_values_to_string( unsigned * value, char * value_s, size_t length ) { value_s[ length ] = '\0'; for( size_t i = length; i != 0; --i ) { unsigned val = value[ i - 1 ]; if( val > 9 ) { fprintf( stderr, "Błąd wartości %u na pozycji %zu.\n", val, i ); exit( EXIT_FAILURE ); } value_s[ i - 1 ] = '0' + val; } size_t count = 0; for(; count <( length + 1 ); ++count ) { if( value_s[ count ] != '0' ) { break; } } return &( value_s[ count ] ); }
void read_value( unsigned * value ) { char * value_s =( char * ) malloc(( MAX_POSITIONS * sizeof( char ) ) + 1 ); memset( value_s, 0,(( MAX_POSITIONS * sizeof( value_s[ 0 ] ) ) + 1 ) ); memset( value, 0,( MAX_POSITIONS * sizeof( value[ 0 ] ) ) ); read_value_string( value_s ); convert_string_to_values( value_s, value ); free( value_s ); }
int main() { unsigned value1[ MAX_POSITIONS ]; unsigned value2[ MAX_POSITIONS ]; unsigned result[ MAX_POSITIONS + 1 ]; printf( "Liczba 1: " ); read_value( value1 ); printf( "Liczba 2: " ); read_value( value2 ); printf( "Dodawanie liczb:\n" ); add_values( value1, value2, result ); char result_s[ MAX_POSITIONS + 2 ]; char * str_ptr = convert_values_to_string( result, result_s, MAX_POSITIONS + 1 ); printf( "%s\n", result_s ); printf( "%s\n", str_ptr ); return EXIT_SUCCESS; }
|
|
Beli Temat założony przez niniejszego użytkownika |
» 2016-12-28 17:03:23 Dziękuję, bardzo mi to pomogło. Spróbowałem zrobić odejmowanie wg schemat mateczka, nie bardzo mam tylko pomysł na dokończenie. int Odejmowanie( char X[], char Y[], char Z[], int SIZE ) { int i, roznica; int p = 0; Z[ SIZE + 1 ] = '\0'; for( i = SIZE - 1; i >= 0; i-- ) { roznica = X[ i ] - '0' - Y[ i ] + '0' + p; Z[ i + 1 ] = roznica % 10 + '0'; p = roznica / 10; if( p == 0 ); else { roznica = X[ i ] - '0' - Y[ i ] + '0' + p; Z[ i + 1 ] = roznica % 10 + 10 + '0'; p = roznica / 10 - 1; } } Z[ 0 ] = p + '0'; return p; }
Ogółem wszystko działa wtedy, gdy nie korzystam w ogóle ze zmiennej p (innymi słowy p=0), tj. nie ma konieczności "pożyczania" wartości od wyższych rzędów, np. dla 55555-44444. Wtedy korzystamy po prostu z tego fragmentu: roznica = X[ i ] - '0' - Y[ i ] + '0' + p; Z[ i + 1 ] = roznica % 10 + '0'; p = roznica / 10;
Jeśli jest konieczność "pożyczenia" wartości z rzędu wyższego, tzn. p jest jakąś liczbą ujemną, trzeba zmienić instrukcję w pętli na taką: roznica = X[ i ] - '0' - Y[ i ] + '0' + p; Z[ i + 1 ] = roznica % 10 + 10 + '0'; p = roznica / 10 - 1;
No ale mam problem żeby to zaprogramować - moja idea jest taka jak w kodzie u góry, jeśli p=0 to nie robimy nic, po prostu kontynuujemy pętlę for. Jeśli natomiast p nie jest równe 0, to należy zmienić instrukcję pętli na taką jak powyżej napisałem. Jeżeli po wykonaniu obrotu tej pętli otrzymamy p=0 to wracamy do pierwotnych instrukcji pętli, jeśli p inne niż 0 to dalej robimy tę nową instrukcję. Wydaje mi się że algorytm jest poprawny, ale nie wiem jak mogę go zamienić na kod w C. Chciałem posłużyć się if-em i dla p==0 zastosować instrukcję pustą. Ale co dać w else żeby działało to zgodnie z oczekiwaniami? A może ktoś ma jakiś prostszy pomysł na rozwiązanie tego? //edit: już sobie poradziłem, w bardzo prosty sposób, działa poprawnie dla dowolnych liczb naturalnych pod warunkiem że pierwsza jest wieksza od drugiej, ale powiedzmy że tu wystarczy odwrócić kolejność i wstawić minus przed wynikiem: int Odejmowanie( char X[], char Y[], char Z[], int SIZE ) { int i, roznica; int p = 0; Z[ SIZE + 1 ] = '\0'; for( i = SIZE - 1; i >= 0; i-- ) { roznica = X[ i ] - '0' - Y[ i ] + '0' + p; if( roznica >= 0 ) { Z[ i + 1 ] = roznica % 10 + '0'; p = roznica / 10; } else { Z[ i + 1 ] = roznica % 10 + 10 + '0'; p = roznica / 10 - 1; } } Z[ 0 ] = p + '0'; return p; }
|
|
« 1 » 2 |