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

Działania na stringach

VPS Starter Arubacloud
0 głosów
1,765 wizyt
pytanie zadane 15 grudnia 2017 w C i C++ przez n0s1gnal Użytkownik (700 p.)
Cześć, potrzebuję dokonać działania(dodawnie i odejmowanie) na liczbach w stringach

string a = "10";

string b = "20";

b - a => "10";

Z góry dzięki za pomoc ;)

Uwaga: Jeśli chcecie odpowiedzieć, "Lepiej zrób to w intach", "Po co Ci w stringach, jak możesz w intach", etc to się nie wysilajcie i wyjdźcie z pytanka ;)
komentarz 15 grudnia 2017 przez Alvancaran Dyskutant (8,160 p.)
Zamieniasz na inty i wykonujesz dzialanie, potem mozesz znowu zamienic na stringa. Inaczej sie nie da
komentarz 15 grudnia 2017 przez n0s1gnal Użytkownik (700 p.)
"Uwaga: Jeśli chcecie odpowiedzieć, "Lepiej zrób to w intach", "Po co Ci w stringach, jak możesz w intach", etc to się nie wysilajcie i wyjdźcie z pytanka ;)"
komentarz 16 grudnia 2017 przez adrian17 Ekspert (344,100 p.)

"Uwaga: Jeśli chcecie odpowiedzieć, "Lepiej zrób to w intach", "Po co Ci w stringach, jak możesz w intach", etc to się nie wysilajcie i wyjdźcie z pytanka ;)"

Nie powiedziałeś czemu podejście string->int->string Ci nie pasuje - warto się interesować, bo może to pomóc w znalezieniu roziwązania.

komentarz 16 grudnia 2017 przez n0s1gnal Użytkownik (700 p.)
Robię odejmowanie na liczbach 10^1000, trochę ciężko na intach ;)

4 odpowiedzi

+2 głosów
odpowiedź 15 grudnia 2017 przez Snejki Stary wyjadacz (14,520 p.)
Najłatwiej to chyba zrobić jako dodawanie/odejmowanie pisemne jak w podstawówce uczyli.
+1 głos
odpowiedź 16 grudnia 2017 przez adrian17 Ekspert (344,100 p.)
edycja 17 grudnia 2017 przez adrian17

Robię odejmowanie na liczbach 10^1000, trochę ciężko na intach ;)

O, tego się spodziewałem :)

No to idealnie byłoby żeby, zamiast używać atrapy w postaci std::stringa, użyć dedykowanej biblioteki do operacji na dowolnie dużych liczbach, np boost::multiprecision:

#include <boost/multiprecision/cpp_int.hpp>
#include <iostream>

using boost::multiprecision::cpp_int;
using boost::multiprecision::pow;

int main()
{
	cpp_int liczba = 10;
	liczba = pow(liczba, 1000);
	liczba += 1234;

	std::cout << liczba;
}

Albo, już wychodząc na boczny tor, użyć języka który coś takiego ma wbudowane :P

liczba = 10**1000
liczba += 1234

print(liczba)

 

komentarz 17 grudnia 2017 przez mokrowski Mędrzec (155,460 p.)
Ogólnie racja. Przy którymś zadaniu ze SPOJ'a naklepałem sobie kod w tym wątku. Ale nikt normalny nie będzie używał takich konstrukcji w projektach :-)
0 głosów
odpowiedź 15 grudnia 2017 przez niezalogowany

std::string to tablica zmiennych typu char, które można zamienić na cyfrę (zgodnie z tablicą ASCII). Czyli używając odpowiednich zmian możesz zrobić funkcję dodającą dwie tablice cyfr - zwyczajnie "jak w podstawówce uczyli.". Czyli dodajesz dwie liczby i i reszte z dzielenia przez 10 zapisujesz na i-tej pozycji w tablicy wynikowej, a tą część liczby która się nie mieści musisz dodać następnym razem na i+1 pozycji itd. Takie dodawanie będzie wolniejsze niż na intach, będzie zajmować więcej pamięci, ale ograniczenie jej wielkości liczby będzie znacznie znacznie większe. Mam nadzieję, że o to chodziło.

Możesz się pokusić też o zrobienie tego w formie klasy BigInt z przeciążonymi operatorami (tak dla walorów estetycznych):

class BigInt
{
    std::string number;
public
	friend std::string operator+ (BigInt a, BigInt b)
//...
};

0 głosów
odpowiedź 16 grudnia 2017 przez mokrowski Mędrzec (155,460 p.)
#include <string>
#include <stdexcept>
#include <iostream>
#include <cctype>
#include <cassert>

class NumericString {
public:

    NumericString(): data{"0"} {}

    NumericString(const std::string& data_): data{data_} {
        NumericString::not_digit_throw(data);
    }

    NumericString(const char * data_): data(data_) {
        NumericString::not_digit_throw(data);
    }

    NumericString(const NumericString& src) {
        NumericString::not_digit_throw(src.data);
        data = src.data;
    }

    NumericString& operator=(const std::string& data_) {
        NumericString::not_digit_throw(data_);
        data = data_;
        return *this;
    }

    NumericString& operator=(const char * data_) {
        return operator=(std::string(data_));
    }

    NumericString& operator+(const std::string& data_) {
        NumericString::not_digit_throw(data_);
        add_string(data_);
        return *this;
    }

    NumericString& operator+(const NumericString& src) {
        return operator+(src.data);
    }

    NumericString& operator+(const char * data_) {
        return operator+(std::string(data_));
    }

    NumericString& operator+=(const NumericString& src) {
        return operator+(src.data);
    }

    NumericString& operator+=(const std::string& data_) {
        return operator+(data_);
    }

    NumericString& operator+=(const char * data_) {
        return operator+(std::string(data_));
    }

    const std::string& to_string() const {
        return data;
    }

    const char * c_str() const {
        return data.c_str();
    }


private:
    static bool not_digit_throw(const std::string& data_) {
        return not_digit_throw(data_.c_str());
    }

    static bool not_digit_throw(const char * data_) {
        char * ptr = const_cast<char *>(data_);
        while(*ptr != 0) {
            if(! std::isdigit(*ptr)) {
                throw std::invalid_argument("NumericString illegal char. Only digit allowed.");
            }
            ++ptr;
        }
        if(*data_ == 0) {
            throw std::invalid_argument("Empty string not allowed.");
        }
        return true;
    }

    void add_string(const std::string& value) {
        auto& longer_string = choice_longer_string(data, value);
        auto result = "0" + longer_string;
        auto& added_string = longer_string == data ? value : data;
        auto added_index = added_string.size();
        auto result_index = result.size() - 1;
        auto carry = 0U;

        while(added_index--) {
            unsigned value = result[result_index] + added_string[added_index] + carry;
            if(value > ('0' + '9')) {
                value -= 10;
                carry = 1; 
            } else {
                carry = 0;
            }
            result[result_index--] = value - '0';
        }

        carry_propagation(result, result_index, carry);

        data = remove_leading_zeros(result);
    }

    const std::string& choice_longer_string(const std::string& s1, const std::string& s2) {
        return s1.size() > s2.size() ? s1: s2;
    }

    void carry_propagation(std::string& result, size_t result_index, unsigned carry) {
        while(carry) {
            auto value = result[result_index] + carry;
            if(value > '9') {
                result[result_index] = value - 10;
                carry = 1;
            } else {
                result[result_index] = value;
                carry = 0;
            }
            --result_index;
        }
    }

    std::string remove_leading_zeros(std::string& value) {
        auto const pos = value.find_first_not_of('0');
        value.erase(0, pos);

        return value.size() ? value: "0";
    }

    std::string data;
};

int main() {
    NumericString number1{"1410"};
    NumericString number2{"1919"};
    NumericString number3 = "9999";
    number3 += "9999";
    NumericString number4 = "0";
    number4 += "0";
    NumericString number5 = "8788936827674961256837936320935798358762176805849872";
    number5 +="8989254213765729837187205937498218778687350304912821464";
    assert(number5.to_string() == "8998043150593404798444043873819154577046112481718671336");
    std::cout << number3.c_str() << std::endl;
    std::cout << (number1 + number2).to_string() << std::endl;
    std::cout << number4.c_str() << std::endl;
    std::cout << number5.c_str() << std::endl;
}

 

Podobne pytania

0 głosów
2 odpowiedzi 1,162 wizyt
pytanie zadane 26 grudnia 2017 w C i C++ przez DeMS Nowicjusz (150 p.)
0 głosów
0 odpowiedzi 122 wizyt
pytanie zadane 27 grudnia 2019 w C i C++ przez amtrax Dyskutant (9,630 p.)
0 głosów
0 odpowiedzi 562 wizyt
pytanie zadane 28 października 2016 w Rozwój zawodowy, nauka, praca przez Roksana Nowicjusz (120 p.)

92,454 zapytań

141,262 odpowiedzi

319,098 komentarzy

61,854 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

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 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!

...