• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Zadanie z C++

Object Storage Arubacloud
+1 głos
233 wizyt
pytanie zadane 4 stycznia w C i C++ przez WirusTrojan Nowicjusz (130 p.)

Celem zadania jest napisanie programu który będzie potrafił wykonywać operacje matematyczne (dodawanie, odejmowanie, mnożenie i dzielenie) na bardzo dużych liczbach całkowitych. Bardzo dużych czyli takich które nie mieszczą się w zmiennej typu Int, np. 100 cyfrowych. 
jako wejście podawane jest String zawierający conajmniej dwie liczby i conajmniej jedno działanie do wykonania. Należy tutaj również pamiętać o kolejności wykonywania działań gdyż nawiasy są dozwolone. 
w wyniku operacji na obiekcie typu String oczekiwane jest wypisanie obiektu String który zawiera rezultat operacji. 
Nie dozwolone jest używanie niczego spoza biblioteki iostreamsmiley ktoś pomoże bo już troszke wymiękam przy biurku

2 odpowiedzi

+2 głosów
odpowiedź 5 stycznia przez Gynvael Coldwind Nałogowiec (27,530 p.)

@WirusTrojan jeśli tego nigdy nie pisałeś, to to Ci zajmie kilka wieczorów, ale jest jednocześnie dobrze opisane na necie; zacznij na początku od zaimplementowania "pisemnego" dodawania/mnożenia/etc, tj. rozbij sobie każdą liczbę na tablice cyfr, i zaimplementuj algorytm, który wylicza wynik tak jak się w podstawówce na kartce uczyłeś.

Jak to będziesz miał i będzie dobrze działać, to kolejnym krokiem jest parsing/tokenizacja wyrażenia które dostajesz (tego "(1000+22222)*3+4567") na tokeny, tj. listę zrozumiałych dla programu obiektów, gdzie każdy obiekt reprezentuje jedną logiczną część wyrażenia. W przypadku przykładu to by było coś w stylu:

Notacja: typ tokenu, opcjonalny parametr (string)

TOKEN_PARENTHESIS_OPEN
TOKEN_NUMBER, "1000"
TOKEN_OP_ADD
TOKEN_NUMBER, "22222"
TOKEN_PARENTHESIS_CLOSE
TOKEN_OP_MUL
TOKEN_NUMBER, "3"
TOKEN_OP_ADD
TOKEN_NUMBER, "4567"

Mając taką listę tokenów, możesz programowo na nich operować.

I teraz, z uwagi na kolejność operacji, musisz:

1) albo przejść na odwrotną notację polską (RPN), a przynajmniej zbudować drzewo AST (Abstract Syntax Tree) – dowolne z tych pozwoli Ci zacząć w prosty sposób liczyć,

2) albo napisać kilka pętli, gdzie w każdej będziesz znajdować dany typ operacji z większym priorytetem, i podmieniać tokeny na wyniki do skutku, tj:

Przykład:

W pętli pierwszej szukasz wszystkich TOKEN_OP_MUL (oraz _DIV) które
mają TOKEN_NUMBER po obu stronach, np.:

TOKEN_NUMBER, "2"
TOKEN_OP_MUL
TOKEN_NUMBER, "6"

I je zamieniasz in-place na token z wynikiem (tj. zamieniasz 
pierwszy number i usuwasz dwa pozostałe tokeny):

TOKEN_NUMBER, "12"

W drugiej pętli robisz to samo dla TOKEN_OP_ADD i TOKEN_OP_SUB.

W trzeciej pętli szukasz wszystkich nawiasów z liczbą w środku, i usuwasz 
nawiasy, tj.

TOKEN_PARENTHESIS_OPEN
TOKEN_NUMBER, "1234"
TOKEN_PARENTHESIS_CLOSE
↓
TOKEN_NUMBER, "1234"

I te 3 pętle powtarzasz do póki wielkość listy tokenów != 1

Na końcu będziesz miał jeden token z wynikiem na liście.

Od razu mówię, że to jest trochę hack i jest wolniejsze niż AST/RPN, ale jest też dużo prostsze w implementacji.

komentarz 5 stycznia przez Gynvael Coldwind Nałogowiec (27,530 p.)
A, i uwaga na słowo "całkowite" – Twój kod MUSI też liczby ujemne ogarniać.
2
komentarz 5 stycznia przez adrian17 Ekspert (344,860 p.)
1. brzmi dla mnie trochę odwrotnie, bo RPN (w sensie przynajmniej shunting yard i na bieżąco liczenie, nie trzeba przechowywać całego wynikowego RPN) brzmi prościej niż budowanie AST?
–1 głos
odpowiedź 4 stycznia przez dia_Chann Nowicjusz (180 p.)
edycja 5 stycznia przez Arkadiusz Waluk
#include <iostream>

#include <string>

 

std::string add(const std::string& num1, const std::string& num2) {

    return std::to_string(stoll(num1) + stoll(num2));

}

 

std::string subtract(const std::string& num1, const std::string& num2) {

    return std::to_string(stoll(num1) - stoll(num2));

}

 

std::string multiply(const std::string& num1, const std::string& num2) {

    return std::to_string(stoll(num1) * stoll(num2));

}

 

std::string divide(const std::string& num1, const std::string& num2) {

    if (stoll(num2) == 0) {

        return "Error: Division by zero";

    }

    return std::to_string(stoll(num1) / stoll(num2));

}

 

int main() {

    std::string num1, num2;

 

    std::cout << "Podaj pierwszą liczbę: ";

    std::getline(std::cin, num1);

 

    std::cout << "Podaj drugą liczbę: ";

    std::getline(std::cin, num2);

 

    std::string sum = add(num1, num2);

    std::string difference = subtract(num1, num2);

    std::string product = multiply(num1, num2);

    std::string quotient = divide(num1, num2);

 

    std::cout << "Suma: " << sum << std::endl;

    std::cout << "Różnica: " << difference << std::endl;

    std::cout << "Iloczyn: " << product << std::endl;

    std::cout << "Iloraz: " <<

quotient << std::endl;

 

    return 0;

}
komentarz 5 stycznia przez Gynvael Coldwind Nałogowiec (27,530 p.)

@adrian17, jeśli mnie pamięć nie myli, u nas na studiach dali VLI/biginty po prostu na liście zadań ćwiczeniowych ze Wstępu do Programowania, bez tłumaczenia :D (tłumaczenie było pół roku później na Algorytmach i Strukturach Danych). Ale in all fairness nie było tam żadnych wyrażeń jak tutaj.

komentarz 5 stycznia przez Oscar Nałogowiec (29,320 p.)

@WirusTrojan, To akurat jest prosto oszacować - 3 cyfry dziesiętne (1000) odpowiada dość dokładnie 10 bitom (1024) czyli 100 cyfr dziesiętnych to ok 330 bitów.

komentarz 16 stycznia przez WirusTrojan Nowicjusz (130 p.)
edycja 17 stycznia przez WirusTrojan

@dia_Chann, chciałym sie zapytać czemu dwie dodatnie liczby na suma wychodzi ujemna?? tak samo jak na mnożeniu

Próbuje coś  jakoś to rozwiązać

komentarz 18 stycznia przez TOWaD Mądrala (6,000 p.)
edycja 20 stycznia przez TOWaD

Może to jest spowodowanie przekroczeniem zakresu. Np:

#include <iostream>
using namespace std;
int main()
{
    //INT_MAX 	Maksymalna wartość zmiennej typu int. 	2147483647
    cout<<"INT_MAX="<<static_cast<int>(2147483647)<<'\n'; //2147483647
    cout<<"INT_MAX+1= "<<static_cast<int>(2147483648)<<'\n'; //-2147483648
    //UINT_MAX 	Maksymalna wartość zmiennej typu unsigned int. 	4294967295
    cout<<"UINT_MAX = "<<static_cast<unsigned int>(4294967295)<<'\n'; //4294967295
    cout<<"rzutowanie na INT= "<<static_cast<int>(4294967295)<<endl; //-1
    return 0;
}

to samo [online]

edit:: oczywiście nalezys się zapoznać co najmniej z tym lub z tym. Przypisanie wartości większej niż zarezerwowana do zmiennej to poważny błąd.

komentarz 18 stycznia przez TOWaD Mądrala (6,000 p.)

A tutaj moja taka propozycja (na razie dodawanie liczb dodatnich i niekoniecznie poprawnie : ) ): tylko: nie nie umiem c++ i używam go rzadko i tylko hobbistycznie, wiec:

1) Projekt nie ma wartości merytorycznych.

2) Będzie miał może wartości edukacyjne jak dodam opisy. I jak będę miał czas i natchnienie by skończyć.

3) Myślę trochę inny pomysł niż ogólnie na forach. Polega na trzymaniu wartości w tablicach char cyfry w odwrotnej kolejności i używanie char jako liczby.

 

Nie znaleziono podobnych pytań

92,584 zapytań

141,433 odpowiedzi

319,666 komentarzy

61,966 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...