Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Помогите написать элегантнее 
:(
    Опции темы
cppGhost
Дата 21.7.2016, 18:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 101
Регистрация: 24.4.2013

Репутация: нет
Всего: нет



Уважаемые тру программисты. Я написал класс для сложения больших чисел. Но вот смотрю на код и понимаю, что написано коряво. Смысл функции вроде бы прост. Идем справа налево и складываем числа, запоминая остаток. Глядя на код opensource проектов и прочее, мне кажется, что моё творение явно можно написать лучше. Тут и много строк, и как-то нелаконично, и куча переменных, несколько if. Помогите мне стать лучше, пожалуйста.

Код

              CBigNumber Sum(CBigNumber &rhs)
    {
        int overhead = 0;
        CBigNumber newNumber;

        list<int>::reverse_iterator it1 = m_values.rbegin();
        list<int>::reverse_iterator it2 = rhs.m_values.rbegin();

        while(it1 != m_values.rend() || it2 != rhs.m_values.rend())
        {
            int num1 = 0;
            if(it1 != m_values.rend())
                num1 = *it1++;            

            int num2 = 0;
            if(it2 != rhs.m_values.rend())
                num2 = *it2++;

            int value = num1 + num2 + overhead;
            if(value >= 10)
            {
                overhead = value / 10;
                value = value % 10;                
            }    
            else
            {
                overhead = 0;
            }

            newNumber.m_values.push_front(value);            
        }

        if(overhead)
            newNumber.m_values.push_front(overhead);

        return newNumber;
    };


Это сообщение отредактировал(а) cppGhost - 21.7.2016, 18:33
PM MAIL   Вверх
baldman88
Дата 21.7.2016, 21:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 210
Регистрация: 18.1.2009

Репутация: 3
Всего: 7



Самое очевидное -- зачем на каждой итерации создавать новые переменные для num1 и num2? Создайте их вместе с overhead. С value аналогично.
Пы.Сы.: я не тру, если что  smile 

Это сообщение отредактировал(а) baldman88 - 21.7.2016, 21:10
PM MAIL   Вверх
borisbn
Дата 22.7.2016, 10:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Цитата(baldman88 @  21.7.2016,  21:02 Найти цитируемый пост)
Самое очевидное -- зачем на каждой итерации создавать новые переменные для num1 и num2? Создайте их вместе с overhead. С value аналогично.

Их всё равно нужно обнулять на каждой итерации, а создание переменной на стеке вообще ничего не стоит.

По вопросу - как по мне, так вполне себе нормальный и, самое главное, - понятный код. ИМХО не стОит усложнять.... Работает (да ещё и понятно написано) - не трогай. (С) кто-то там
Цитата(cppGhost @  21.7.2016,  18:28 Найти цитируемый пост)
overhead = value / 10;

а вместо этого можно просто написать
Код
overhead = 1;



--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
xvr
Дата 22.7.2016, 11:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Можно написать короче, но отнюдь не понятнее  smile Возникает вопрос - а оно надо?
Код

              CBigNumber Sum(CBigNumber &rhs)
    {
        int overhead = 0;
        CBigNumber newNumber;
        list<int>::reverse_iterator it1 = m_values.rbegin();
        list<int>::reverse_iterator it2 = rhs.m_values.rbegin();
        while(it1 != m_values.rend() || it2 != rhs.m_values.rend())
        {
            int num1 =  it1 != m_values.rend() ? *it1++ : 0;            
            int num2 =  it2 != rhs.m_values.rend() ? *it2++ : 0;
            int value = num1 + num2 + overhead;
            overhead = value >= 10 ? (value-=10,1) : 0;
            newNumber.m_values.push_front(value);            
        }
        if(overhead)
            newNumber.m_values.push_front(overhead);
        return newNumber;
    };


Добавлено @ 11:48
PS. Еще можно вычисления num1 и num2 подставить непосредственно в место использования (стр 11), но это уже совсем монстр будет smile

Это сообщение отредактировал(а) xvr - 22.7.2016, 11:49
PM MAIL   Вверх
cppGhost
Дата 22.7.2016, 12:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 101
Регистрация: 24.4.2013

Репутация: нет
Всего: нет



Всем большое спасибо. Вообще это вечный для меня вопрос. Мне тоже кажется, что код более менее понятен (ну если комментами еще разбавить чуток, то вообще всё разжевано будет). И в нём должен разобраться вообще любой. Но, глядя на реализаии других подобных вещей, мне код кажется ущербным, ну и я туда же)) Например, это из библиотеки InfInt

Код

inline const InfInt& InfInt::operator+=(const InfInt& rhs)
{
    if (rhs.val.size() > val.size())
    {
        val.resize(rhs.val.size(), 0);
    }
    for (size_t i = 0; i < val.size(); ++i)
    {
        val[i] = (pos ? val[i] : -val[i]) + (i < rhs.val.size() ? (rhs.pos ? rhs.val[i] : -rhs.val[i]) : 0);
    }
    correct();
    return *this;
}


всё как-то инкапсулировано, смысл спрятан. я вообще не понимаю, что тут происходит и как можно складывать числа слева направо (ну если только порядок не поменян специально).
но, сравнивая моего монстра с этим,  я бы, наверное, сам отдал предпочтение этому человеку, нежели себе))

Это сообщение отредактировал(а) cppGhost - 22.7.2016, 12:06
PM MAIL   Вверх
borisbn
Дата 22.7.2016, 17:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Посмотрел на реализацию "этого человека" и понял, что у Вас не учитывается знак.. Т.е. Ваш код должен работать только с положительными числами ?


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Remiznik
Дата 22.7.2016, 18:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 379
Регистрация: 30.4.2005

Репутация: нет
Всего: 1



По поводу первого варианта кода. 
Обязательно ли  m_values.rend() и rhs.m_values.rend() вызывать на каждой итерации цикла ? может можно сохранить в переменных перед началом цикла ?
PM MAIL   Вверх
volatile
Дата 22.7.2016, 19:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



Этот код, практически бесполезен. Во первых из-за жуткого оверхеда. На 1 десятичный разряд используется как минимум 12 байт (инт + 2 указателя в листе) в 64-разрядных ОС еще больше...
Кроме того он не поддерживает отрицательные числа (об этом уже писали), а следовательно и вычитание будет нереализуемо.

Имхо надо писать в шестнадцатиричном виде, верней в нативном формате int, и использовать вектор
И это тот случай, когда на асме код получится проще, (в виду доступности флага переполнения)

Из того что можно сократить, первое что бросиось в глаза:
Цитата(cppGhost @  21.7.2016,  18:28 Найти цитируемый пост)
            int value = num1 + num2 + overhead;
            if(value >= 10)
            {

                overhead = value / 10;
                value = value % 10;                
            }    
            else
            {
                overhead = 0;
            }

            newNumber.m_values.push_front(value);            
        }



Это сообщение отредактировал(а) volatile - 22.7.2016, 19:36
PM MAIL   Вверх
volatile
Дата 22.7.2016, 19:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



Цитата(cppGhost @  21.7.2016,  18:28 Найти цитируемый пост)
       return newNumber;

и да, возвращать лист копированием, тоже не айс, мягко говоря.
лучше использовать в качестве базового сложения +=, т.е. складывать к уже имеющемуся
при необходимости простой + можно реализовать через него.

PM MAIL   Вверх
cppGhost
Дата 27.7.2016, 19:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 101
Регистрация: 24.4.2013

Репутация: нет
Всего: нет



Спасибо. Про отрицательные числа - это у меня просто задача в моей вакуумной голове, поэтому просто не думал об этом.
Про лишние строки, спасибо, действительно лишнее.  А про реализацию с шестнадцатеричными числами, тут я не понял((
PM MAIL   Вверх
volatile
Дата 29.7.2016, 10:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



Цитата(cppGhost @  27.7.2016,  19:50 Найти цитируемый пост)
А про реализацию с шестнадцатеричными числами, тут я не понял(( 

Я имел в виду двоичный формат (тот формат в котором работает процессор). это значительно повысит эффективность и упростит реализацию других арифметических функций (пожалуй кроме вывода в десятичном виде).

Впрочем для новичка это будет пожалуй сложновато, и в учебных целях можно оставить и десятичный.
но хотябы тогда уж использовать vector<unsigned char>, а не list<int>

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1525 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.