0 / 0 / 0
Регистрация: 03.06.2011
Сообщений: 12
|
|
1 | |
Классы, Длинная арифметика, LongLong17.06.2011, 22:25. Показов 3537. Ответов 17
Метки нет (Все метки)
Добрый день,
Задание изначально было такое: Реализовать класс Money , используя для представления рублей класс LongLong. Класс Money - представлен двумя полями LongLong для рублей и unsigned char для копеек. Дробная часть (копейки) при выводе на экран должна быть отделена от целой части запятой. Реализовать сложение, вычитание, деление сумм, деление суммы на дробное число, умножение на дробное число и операции сравнения. Класс LongLong для работы с целыми числами из 64 бит. Число должно быть представлено двумя полями: unsigned long — старшая часть, unsigned long — младшая часть. Должны быть реализованы арифметические операции, присутствующие в С++ (без присваивания), и сравнения. Класс Money реализовал, а проблема в следующем: Сложение и умножение для LongLong довольно просто реализуется - складываем левые части, складываем правые. Если в левой появился новый разряд, прибавляем в правую. Вычитание тоже ясно, а как быть с умножением?! Как перемножить два longlong если они каждый из двух частей, причём long. Сколько где разрядов получится? Как сделать чтобы не сильно не вылез? А деление я вообще сложно представляю... В общем, меня как раз и волнуют реализация умножения и деления. Буду рад любым советам. Видел на форуме Валерия Викторовича. Буду очень признателен, если он объяснит какими методами предполагалось решение его задач.
0
|
17.06.2011, 22:25 | |
Ответы с готовыми решениями:
17
Длинная арифметика Длинная арифметика)) Длинная арифметика длинная арифметика |
2381 / 1665 / 279
Регистрация: 29.05.2011
Сообщений: 3,399
|
|
17.06.2011, 23:01 | 2 |
Наверное правильнее оперировать понятиями старшая и младшая, а не левая и правая.
Это на ассемблере просто, там флаг переноса есть. На Си всё-таки посложнее. Ну ладно, будем считать, что просто. Для умножения могу посоветовать помедитировать над следующей формулой. Предположим, что у нас есть числа размером 2*n разрядов. Представим числа A и B половинами по n разрядов A = (Ah << n) + Al B = (Bh << n) + Bl Тогда A*B = ((Ah << n) + Al) * ((Bh << n) + Bl) = (Ah*Bh << 2*n) + ( (Ah*Bl + Al*Bh) << n ) + Al*Bl Добавлено через 4 минуты А деление сдвигами и вычитаниями, как в школе учили — уголком. Медленно, но зато надёжно
0
|
0 / 0 / 0
Регистрация: 03.06.2011
Сообщений: 12
|
|
17.06.2011, 23:23 [ТС] | 3 |
Когда Money делал, та же задача была с рублями и копейками, копейки сложили - получили рубль - отправили в рубль.
Помедитирую, спасибо за формулу. Столбиком? так там же две части? какой алгоритм предполагается?
0
|
2381 / 1665 / 279
Регистрация: 29.05.2011
Сообщений: 3,399
|
|
17.06.2011, 23:33 | 4 |
По-моему это всё-таки называется уголком. В столбик умножают
Предполагается что у нас уже есть реализованные функции сравнения, вычитания и, хотя бы, умножение на 2 (а лучше сдвиг влево). Участвую делимое, делитель и частное сначала делитель сдвигаем влево по одному разряду (умножаем на 2) до тех пор, пока делитель меньше делимого. Количество сдвигов определяет число разрядов целой части частного. Если получим делитель больше делимого, придётся вернуться на разряд назад. Ну а дальше просто. Если делимое больше-равно делителя, вычитаем делитель из делимого и прибавляем к частному единицу. Если меньше — ничего не меняется. Дальше сдвигаем делитель на разряд вправо, частное на разряд влево и повторяем столько раз, сколько нужно Ну, тонкости уже во время реализации продумать можно. Рекомендую поделить разные числа в двоичной форме на листочке вручную
0
|
1069 / 848 / 60
Регистрация: 30.04.2011
Сообщений: 1,659
|
|
18.06.2011, 08:46 | 5 |
1. Умножение можно делать многократным сложением - в цикле
2. Деление можно делать многократным вычитанием - в цикле Сложение младших частей и перенос. 1. Младшая часть LongLong - беззнаковая. 2. Если при сложении получается число, которое меньше обоих слагаемых - значит есть перенос. Проверьте на числах из одной цифры: 6+7 = 13. В младшей части осталось 3 - меньше 6 и меньше 7. Поэтому учесть перенос - легко. Изучайте машинное представление чисел...
0
|
0 / 0 / 0
Регистрация: 03.06.2011
Сообщений: 12
|
|
18.06.2011, 17:28 [ТС] | 6 |
Конечно, уголком... это я утомился и допустил опечатку))
ValeryLaptev, А цикл вы считаете нормальным решением данной задачи? Спасибо за советы, выходные частично посвящу этой задаче. Посмотрим, что получится...
0
|
1069 / 848 / 60
Регистрация: 30.04.2011
Сообщений: 1,659
|
|
18.06.2011, 17:38 | 7 |
Да. Реализовали базовую операцию вычитания, отладили ее. Теперь в делении можно использовать ГАРАНТИРОВАННО правильную функцию. Если ошибки есть, то только в НОВОМ тексте.
0
|
0 / 0 / 0
Регистрация: 03.06.2011
Сообщений: 12
|
|
18.06.2011, 18:03 [ТС] | 8 |
ValeryLaptev,
Это задание можно без перегрузки операторов делать? То есть просто методы класса описать и всё? И потом функции только вызывать? А то я уже задания из второго семинара поделал, там 8-чные числа, 16-чные.. И меня перемкнуло, что здесь тоже нужно перегрузку операторов делать, а это ведь не обязательно да?
0
|
1069 / 848 / 60
Регистрация: 30.04.2011
Сообщений: 1,659
|
|
18.06.2011, 18:48 | 9 |
Да, первый раз - без перегрузки. Потом будет и с конструкторами, и с перегрузкой...
0
|
0 / 0 / 0
Регистрация: 03.06.2011
Сообщений: 12
|
|
20.06.2011, 16:12 [ТС] | 10 |
Возник вопрос
Как быть если с числом 10000000000 в старшую часть поместится 10, а в младшую 000000000. Тогда общее число станет 100, вместо 10000000000. Такая проблема возникает не только при вводе(что я решил), но и при вычитании... как быть?
0
|
2381 / 1665 / 279
Регистрация: 29.05.2011
Сообщений: 3,399
|
|
20.06.2011, 16:16 | 11 |
Непонятно, с чего это общее станет 100? Если старшая часть не равна нулю, то в младшей все нули значащие, и, к примеру, при выводе их нужно будет выводить все.
0
|
0 / 0 / 0
Регистрация: 03.06.2011
Сообщений: 12
|
|
20.06.2011, 16:21 [ТС] | 12 |
так ведь младшая часть у нас unsigned long. а ей что 0, что 0000000. Всё едино. Простой вывод числа - можно организовать, а вот после вычитания как быть. Сносить разряды из старшей части что ли? Так нам нули надо сохранить... или наоборот в старшую часть нули перекидывать?
0
|
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
|
|
21.06.2011, 15:30 | 13 |
Yellow2815, если хоть что-то есть в старшей части, а младшая равна нулю, то в ней на самом деле лежит 20 нулей. Просто запоминаем это и действуем по обстоятельствам.
0
|
0 / 0 / 0
Регистрация: 03.06.2011
Сообщений: 12
|
|
21.06.2011, 17:55 [ТС] | 14 |
silent_1991, )) Это хорошо, для вывода сгодится, а вот при таком числе
1000000000000001, делаем разбиение старшая 1000000 и младшая 000000001. Что в младшей? В общем очень не просто. Длинная арифметика лучше реализуется с массивами.
0
|
2381 / 1665 / 279
Регистрация: 29.05.2011
Сообщений: 3,399
|
|
21.06.2011, 18:03 | 15 |
Хочется кое что уточнить. Я вот всё не могу понять, что же за представление используется для хранения младшей части, если в примерах там 9 разрядов. Кстати, эти разряды двоичные? Если двоичные, то что это, отдельные биты в некоторой целочисленной переменной?
Ну а непосредственно по вопросу, в младшей части число 1. Но при вычитании двойки в младшей части должно оказаться максимально возможное значение этой младшей части. А старшая должна уменьшиться на 1, то есть да — произойдёт заём из старшей части. Для получения полного числа младшая и старшая части складываются (мысленно) с разными весами. Младшая с весом один, старшая с весом равным максимуму младшей плюс один. Добавлено через 50 секунд Если всё не так, то требуется нам подробно объяснить, что понимается под младшей и старшей частями.
0
|
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
|
|
21.06.2011, 18:08 | 16 |
grizlik78, как только переполняется младшая часть, это самое переполнение идёт в старшую.
Yellow2815, у вас абстрактный пример, число полностью поместится в младшей части. А действуем так: если старшая часть не пустая, то берём младшую часть, дописываем к ней спереди нули, которых не хватает, чтобы в общем получилось 20 разрядов - получаем реальную младшую часть, при приклеивании к которой старшей получим исходное число.
0
|
0 / 0 / 0
Регистрация: 03.06.2011
Сообщений: 12
|
|
21.06.2011, 18:09 [ТС] | 17 |
разряды десятичные
В задании указано unsigned long для младшей части и long для старшей. Применяя к классу money для старшей тоже будет unsigned long. undigned long 0..4294967295 чтобы избежать проблем с наибольшим разрядом, я его не стал учитывать и младшая часть максимальная - это 999999999.
0
|
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
|
|
21.06.2011, 18:13 | 18 |
Вернее нет, хранить надо по 19 разрядов, двадцатый - неполноценный :-D
Добавлено через 3 минуты Yellow2815, ах да, я, блин, в уме long long держу, long будет 2^32... Но суть не меняется, просто цифр меньше.
0
|
21.06.2011, 18:13 | |
21.06.2011, 18:13 | |
Помогаю со студенческими работами здесь
18
Длинная арифметика Длинная арифметика Длинная арифметика Длинная арифметика Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |