Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Kalkulator dużych liczb całkowitych

Ostatnio zmodyfikowano 2017-01-12 08:04
Autor Wiadomość
mateczek
» 2016-12-28 19:58:55
Ogólnie ja to dodałem w twoim kodzie to co brakowało do poprawnego działania. Ale nie brał bym się w ten sposób do takiego zadania!!!

Ja bym to zadanie zrobił w sposób jak poniżej. I zamiast sytemu dziesiętnego zastosował bym system. (10 kwadrylion-owy) :P  i 32cyry upakował w tablicy 2 wartości long long :)
jak poniżej.

przykład łopatologiczny bez zabezpieczeń przieniesień tylko szkicujący metodę
C/C++
#include <iostream>
#include<cmath>
using namespace std;
int main() {
    long long big1[ 2 ];
    long long big2[ 2 ];
    string liczba = { "111111111111111122222222222222222" };
    string liczba2 = { "222222222222222111111111111111111" };
   
   
    // rozbić na dwa stringi po 16
    string temp = liczba.substr( 0, 16 );
    big1[ 0 ] = stoll( temp );
   
    temp = liczba.substr( 16, string::npos );
    big1[ 1 ] = stoll( temp );
   
    temp = liczba2.substr( 0, 16 );
    big2[ 0 ] = stoll( temp );
   
    temp = liczba2.substr( 16 );
    big2[ 1 ] = stoll( temp );
   
    //bez przeniesienia dodawanie
    long long wynikl = big1[ 1 ] + big2[ 1 ];
    long long wynikH = big1[ 0 ] + big2[ 0 ];
   
    //
    cout << wynikH << wynikl;
   
   
   
}
i takim oto sposobem zadanie się trywializuje (brak pętli, operujesz na dwóch wartościach, a i pożyczyć jedynkę można w sposób wręcz banalny)
P-155606
Beli
Temat założony przez niniejszego użytkownika
» 2016-12-29 20:46:09
Chciałem jeszcze zadać takie bardziej teoretyczne pytanie.
Jako że umiem z tego C naprawdę niewiele wolę trzymać się jednak pętli i pojęć raczej podstawowych, no i zadziałało to jakoś dla dodawania i odejmowania, nawet rozumiem jak to działa, co już jest małym cudem.
W mnożeniu jednak jest już sporo trudniej, te pętle zagnieżdżone będą w sobie kilkukrotnie, ale na innym forum wyczytałem, że ktoś polecił poradzić sobie z mnożeniem wykorzytsując Dodawanie, tj. 5*5=5+5+5+5+5. No i to już brzmi jak dla mnie dużo prościej, ale czy wywołanie kilkadziesiąt kwadryliardów razy funkcji Dodawanie nie okaże się dla komputera niewykonalne? Nie zależy mi na jakimś super-efektywnym algorytmie, ma to po prostu działać i nie wywołać eksplozji, ale mogę na to liczyć kombinując w tę stronę?
P-155662
mokrowski
» 2016-12-29 21:23:28
1. Dla mnożenia powinieneś alokować miejsce na wynik który jest sumą długości liczb (u Ciebie tablic).
2. Przeczytaj sobie to i powinieneś być w stanie zrealizować mnożenie: http://mmsyslo.pl/content/download/292/1164/version/1/file/Piramidy_szyszki_04.pdf

PS. A tu masz całą książkę autora (nie czytałem ale wygląda lekko i strawnie choć pewnie nie jest to kompendium :-) )
P-155666
Beli
Temat założony przez niniejszego użytkownika
» 2017-01-12 08:04:27
To mam jeszcze jedną prośbę, bo dzieje się coś czego nie jestem w stanie wyłapać. Mam gotowy kalkulator dla dodawania i odejmowania i testowo wyniki pokazywał dobre, ale z jakiegoś powodu wariuje gdy stała SIZE jest większa niż 30. Czemu tak jest - nie mam pojęcia:
C/C++
#include <stdio.h>
#include <stdlib.h>

int Dodawanie( char X[], char Y[], char Z[], int SIZE ) /*podprogram obslugujacy dodawanie liczb naturalnych o danej dlugosci nasladujacy dodawanie pisemne*/
{
    int i, suma;
    int p = 0; /*zmienna ktora wykorzystamy aby zwiekszac nastepny rzad, jesli suma w poprzednim bedzie wieksza niz 10, analogicznie jak w dodawaniu pisemnym*/
    Z[ SIZE + 1 ] = '\0'; /*rezerwujemy ostatnie miejsce w tablicy*/
    for( i = SIZE - 1; i >= 0; i-- )
    {
        suma = X[ i ] - '0' + Y[ i ] - '0' + p; /* '0' jest odpowiednikiem 48, nale¿y to odejmowac od char aby otrzymac szukany int. Przy pierwszym obrocie dodajemy po prostu cyfry jednosci, potem cyfry dziesiatek powiekszone o "nadwyzke z jednosci", czyli p, itd. */
        Z[ i + 1 ] = suma % 10 + '0'; /*poniewaz moze sie zdarzyc tak, ze wynik bedzie mial nie 32, a 33 cyfry, komorka "i+1" wyniku odpowiada komorkom "i" tablic sumowanych. Jesli wynik wyjdzie 32 cyfrowych to nie szkodzi, jako cyfra najwyzszego rzedu wpisane zostanie 0*/
        p = suma / 10; /*p, czyli "nadwyzka", jest liczba calkowita. Zauwazmy, ze jesli przyjmiemy, ze suma jest int, to suma%10+suma/10=suma*/
    }
    Z[ 0 ] = p + '0'; /*tutaj wlasnie miejsce najwyzszego rzedu w wyniku okazuje sie albo zerem, albo nadwyzka z dodawania najwyzszych rzedow tablic sumowanych*/
    return p;
}
int Odejmowanie( char X[], char Y[], char Z[], int SIZE ) /*podprogram obslugujacy odejmowanie liczb naturalnych o danej dlugosci nasladujacy odejmowanie pisemne*/
{
    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; /*tak jak w Dodawaniu dodawalismy komorki, tak tu je odejmujemy w analogicznej petli*/
        if( roznica >= 0 ) /*jesli roznica w danym rzedzie jest nieujemna nic specjalnego nie musimy robic: p=0, a w tablicy wyniku zapisujemy po prostu roznice dwoch cyfr*/
        {
            Z[ i + 1 ] = roznica % 10 + '0';
            p = roznica / 10;
        }
        else /*jesli roznica jest ujemna to "pozyczamy" od wyrazu wyzszego rzedu, zmniejszajac go o 1 i dodajac jednoczesnie 10 do wyrazu nizszego rzedu - tak samo jak w odejmowaniu pisemnym*/
        {
            Z[ i + 1 ] = roznica % 10 + 10 + '0';
            p = roznica / 10 - 1;
        } /*problem pojawia sie gdy od mniejszej liczby odejmujemy wieksza, ale rozwiazujemy go dalej, juz w menu kalkulatora*/
    }
    Z[ 0 ] = p + '0'; /*w odejmowaniu nie ma to juz takiego znaczenia jak w dodawniu, ale zostawmy by sposob wyswietlania wyniku byl taki sam jak w podprogramie Dodawanie, z zerem na poczatku*/
    return p;
}

int main()
{
    int symbol, symbol2; /* do przechowania symboli liczb, dzieki temu obslugujemy nie tylko liczby naturalne, ale i calkowite */
    int operacja; /* do switch, wybiera dodawanie lub odejmowanie */
    const int SIZE = 32; /*dzieki const mozemy w razie potrzeby zmienic program by dzialal nie tylko dla liczb 32-cyfrowych, ale i dla wiekszych lub mniejszych. Przydatne rowniez gdy chcemy przetestowac jego dzialanie - zmieniamy po prostu SIZE na mniejsza liczbe i jest wygodniej sledzic poprawnosc wyniku */
   
    printf( "KALKULATOR DODAWANIA I ODEJMOWANIA\n"
    "----------------------------------------------------------------------------\n"
    "Podaj symbol przed liczba, ktorej modul jest wiekszy (wybierz 1 jesli + lub 2 jesli -): \n" );
    scanf( "%d", & symbol );
    printf( "Podaj modul tej liczby: \n" );
    char A[ SIZE ]; /* liczby sa na tyle duze, ze musimy je przechowywac w tablicach. Miejsca od 0 do SIZE-1 sa przeznaczone na cyfry, miejsce SIZE jest zarezerwowane jako ostatnia komorka tablicy */
    scanf( "%s", A );
   
    printf( "Podaj symbol przed druga liczba (wybierz 1 jesli + lub 2 jesli -): \n" );
    scanf( "%d", & symbol2 );
    printf( "Podaj modul drugiej liczby: \n" );
    char B[ SIZE ];
    scanf( "%s", B );
   
    char C[ SIZE + 1 ]; /* tablica C przechowuje wynik, dlatego musi byc wieksza od pozostalych tablic - suma dwoch liczb dodatnich 32-cyfrowych moze miec 33 cyfry, podobnie jak roznica dwoch liczb ujemnych*/
    printf( "Wybierz operacje: \n1. Dodawanie. \n2. Odejmowanie. \nInny: Opusc program\n" );
    scanf( "%d", & operacja );
   
    switch( operacja ) /*warunek wielokrotnego wyboru switch pozwala nam wykorzystac funkcje napisana dla liczb naturalnych w ten sposob, by dzialala takze dla liczb calkowitych */
    {
    case 1:
        {
            if( symbol == 1 && symbol2 == 1 ) /*zwyczajna suma liczb naturalnych ktorej dzialanie wynika wprost z podprogramu Dodawanie*/
            {
                Dodawanie( A, B, C, SIZE );
                printf( "Dodawanie: %s \n", C );
            }
            else if( symbol == 1 && symbol2 == 2 ) /*sume liczby dodatniej i ujemnej odczytujemy jako roznice modulow tych dwoch liczb*/
            {
                Odejmowanie( A, B, C, SIZE );
                printf( "Dodawanie: %s \n", C );
            }
            else if( symbol == 2 && symbol2 == 1 ) /*analogicznie jak powyzej, dopisujemy jednak minus, bo liczba ujemna ma wiekszy modul*/
            {
                Odejmowanie( A, B, C, SIZE );
                printf( "Dodawanie: -%s \n", C );
            }
            else /*suma 2 liczb ujemnych odczytywana jest jako suma ich modulow z dopisanym minusem*/
            {
                Dodawanie( A, B, C, SIZE );
                printf( "Dodawanie: -%s \n", C );
            }
            break;
        }
    case 2:
        {
            if( symbol == 1 && symbol2 == 1 ) /*zwyczajna roznica liczb naturalnych ktorej dzialanie wynika wprost z podprogramu Odejmowanie. Pamietamy, ze pierwsza z wpisanych liczb jest wieksza, o co wczesniej prosilismy wpisujacego i mialo to zastosowanie takze przy dodawaniu*/
            {
                Odejmowanie( A, B, C, SIZE );
                printf( "Odejmowanie: %s \n", C );
            }
            else if( symbol == 1 && symbol2 == 2 ) /*jesli odejmiemy od liczby dodatnia liczbe ujemna to tak naprawde dodajemy ich moduly, wiec wykorzystujemy po prostu podprogram Dodawanie*/
            {
                Dodawanie( A, B, C, SIZE );
                printf( "Odejmowanie: %s \n", C );
            }
            else if( symbol == 2 && symbol2 == 1 ) /*jesli odejmiemy od liczby ujemnej liczbe dodatnia to otrzymamy sume ich modulow zapisana z minusem*/
            {
                Dodawanie( A, B, C, SIZE );
                printf( "Odejmowanie: -%s \n", C );
            }
            else /*roznica 2 liczb ujemnych odczytywana jest jako roznica ich modulow z dolaczonym minusem w wyniku*/
            {
                Odejmowanie( A, B, C, SIZE );
                printf( "Odejmowanie: -%s \n", C );
            }
            break;
        }
        default: /*wyjscie z programu na wypadek gdybysmy pomylili sie przy wpisywaniu liczb, sa raczej dlugie*/
        exit( 0 );
    }
    return 0;
}

Będę wdzięczny za wskazanie gdzie mogę to poprawić, by działało jak należy.
P-156352
1 « 2 »
Poprzednia strona Strona 2 z 2