40 / 13 / 8
Регистрация: 15.12.2009
Сообщений: 70
|
|||||||||||||||||||||
1 | |||||||||||||||||||||
"Учу" длинную арифметику14.07.2011, 20:46. Показов 4869. Ответов 12
Метки нет (Все метки)
Доброго времени суток. Начал пробывать реализовывать длинную арифметику на шарпе, но вышло очень криво, соответственно очень долго(это слабо сказанно). Подскажите как можно оптимизировать. Прошу не писать что-то вроде "Пиши на плюсах" и др. Интересует только шарп.
Сумма
0
|
14.07.2011, 20:46 | |
Ответы с готовыми решениями:
12
Задача на длинную арифметику. Найти количество делителей n-значного натурального числа на длинную арифметику. на длинную арифметику. Задачи на длинную арифметику |
67 / 67 / 9
Регистрация: 18.04.2011
Сообщений: 124
|
||||||
14.07.2011, 21:19 | 2 | |||||
Сообщение было отмечено как решение
Решение
Предложу вариант попроще, если требуется не именно разработка метода своими руками.
3
|
40 / 13 / 8
Регистрация: 15.12.2009
Сообщений: 70
|
|
14.07.2011, 21:22 [ТС] | 3 |
Спасибо конечно большое, однако хочется самому поучится делать такие вещи.
0
|
67 / 67 / 9
Регистрация: 18.04.2011
Сообщений: 124
|
|
14.07.2011, 21:48 | 4 |
А, окей)
Тогда, во-первых, лучше выкинуть все операции со строками - все эти Convert.ToInt16 и ToString очень тормозные. Оставьте их только при вводе чисел, а в самом начале метода, например, разбейте их на байтовые массивы - по разрядам. Потом - при сложении, по-моему, нет никакой необходимости дополнять числа нулями до одинаковых длин. Во-первых, это просто не нужно - определите сначала длину меньшего числа, и ограничьте цикл ей +1 (на случай, если будет остаток в старший разряд). Когда цикл кончается, оставшиеся цифры большего числа просто приписываются к результату слева. Во-вторых, представьте, сколько вы сэкономите времени, когда в примере типа 598374508923540872648572689475623865283+1 избавитесь от 1 -> 000000000000000000000000000000000000001 3+1=4; 8+0=8; 2+0=2; 5+0=5... И при этом каждая цифра парсится в int, а потом обратно. Конечно, оно тормозит. Вычитание: а зачем писать отдельный метод, когда оно ничем не отличается от сложения? Просто опять же, когда будете переводить в массив - умножьте каждое число на -1, и метод сложения будет так же работать. При этом остаток, который переносится в старший разряд, будет получаться отрицательным - когда "занимаем" единицу. Умножение: вы используете "столбиком", умножая число на все цифры по очереди. Есть довольно неплохой выбор алгоритмов быстрого умножения - самый быстрый, емнип, все еще алгоритм Карацубы. Один из самых простых алгоритмов переделан из быстрого возведения в степень: 0. Есть числа a и b 1. Переводим a в двоичную систему 2. Считываем подряд символы (единицы и нули) из a, отбросив первый символ 3. Сохраним изначальное число b как b0 4. На каждом шаге, если полученный символ=0, то b=2b. Если символ=1, то b=2b+b0 Пример: 2*5. 5 в двоичной системе = 101. Отбрасываем первую единицу, остается 01. Первый символ равен 0: умножаем 2 на 2, получаем 4. Второй символ равен 1: умножаем 4 на 2 и прибавляем 2 - получаем искомые 10. Алгоритм не очень выгоден для маленьких чисел (2*5 мы бы получили одной операцией, а тут две), но для больших быстрее, чем столбиком.
2
|
167 / 96 / 23
Регистрация: 13.03.2011
Сообщений: 402
|
|
14.07.2011, 21:50 | 5 |
Попробуйте реализовать через китайскую теорему об остатках.
Дает хороший выигрыш в скорости на * и / Размер чисел ограничен только разумными пределами
1
|
68 / 66 / 19
Регистрация: 27.12.2008
Сообщений: 212
|
|
14.07.2011, 22:21 | 6 |
можно, например, брать не по одному символу а по 18, если использовать long int, в котором до 19 символов может быть
Добавлено через 7 минут эм... 7+4 вроде бы отличается от 7-4 или я неправильно понял?
1
|
40 / 13 / 8
Регистрация: 15.12.2009
Сообщений: 70
|
|||||||||||
14.07.2011, 22:50 [ТС] | 7 | ||||||||||
TO:somethingrotten
Очень много дельный советов - особенно с нулями - спасибо. А вот с вычитанием я тоже не понял... я ведь их взаимозаменяю когда необходимо
Просто когда делаешь что-то на подобии суммы всех чисел от одного до 1000 в степени этого же числа используя вышеупомянутый код, может уйти больше часа... Всё-таки без определённых алгоритмов никуда=) Насчёт long... не знаю склоняюсь всё таки к разбитию числа на байтовый массив... думаю так быстрее будет
0
|
67 / 67 / 9
Регистрация: 18.04.2011
Сообщений: 124
|
||||||||||||||||
14.07.2011, 23:31 | 8 | |||||||||||||||
majesty1992, про вычитание я имел в виду, что у вас для него есть отдельный метод:
Насчет возведения в степень - просто обязательно юзать алгоритм, типа вышеприведенного, в оригинальной форме (формулы соответственно заменяются на b=b^2, если 0 и b=b0*b^2 если 1). Вдвойне обязательно - если это степень по модулю) Up. Кстати, чтобы сделать код проще и красивей, вместо String.Concat можно писать +=. Xero201, я не про результат операции, а про принцип работы сложения) Формула (а значит, метод) не изменится, если в нее подавать отрицательные числа - следовательно, нам нужен всего лишь один метод)
1
|
68 / 66 / 19
Регистрация: 27.12.2008
Сообщений: 212
|
||||||
14.07.2011, 23:34 | 9 | |||||
зацени (тоже на скорую руку)
0
|
40 / 13 / 8
Регистрация: 15.12.2009
Сообщений: 70
|
|
15.07.2011, 00:02 [ТС] | 10 |
Dictionary<char, int> dic;
не знаком с этой конструкцией Короче начну писать с нуля с байтовыми масивами. Я думаю, что если от строк избавлюсь эфективность увеличиться. Умножение - буду пробывать Карацубу.
0
|
3 / 2 / 2
Регистрация: 19.06.2016
Сообщений: 299
|
|
06.05.2018, 18:56 | 11 |
somethingrotten, как и автор, пытаюсь написать класс для длинной арифметики чисел с плавающей запятой.
Если есть два числа дробных ("_" - пустота) : 1234567,8901 ____432,1___ То, если я не ошибаюсь, придется привести эти числа к виду : 1234567,8901 0000432,1000 Иначе как тогда складывать их?
0
|
138 / 101 / 102
Регистрация: 03.02.2014
Сообщений: 427
|
|
06.05.2018, 20:12 | 12 |
Jesterru, можно попробовать использовать структуру на число, например
Код
НАЧСТРУКТ ПОЛЕ мантисса // массив байтов ПОЛЕ порядок // целое число КОНСТРУКТ и делении ещё проще.
1
|
3 / 2 / 2
Регистрация: 19.06.2016
Сообщений: 299
|
|
07.05.2018, 15:47 | 13 |
Антон1985, Я все таки решил, что лучше использовать 1 массив, содержащий и целую, и дробную части, а так же переменную, обозначающую позицию запятой. Для всех операций потребуется только 1 - правильно расположить массивы друг относительно друга, что делается достаточно просто при создании матрицы, даже Array.Resize делать не надо
Добавлено через 2 минуты Сложение - и так все ясно. Вычитание - есть некоторые сложности, но так же все ясно. Умножение - сложнее сложения, но проще вычитания. Деление - Это комбинация сравнения чисел и вычитания, т.е., по-моему, самое сложное, но состоит из простого
0
|
07.05.2018, 15:47 | |
07.05.2018, 15:47 | |
Помогаю со студенческими работами здесь
13
Задача на длинную арифметику Задача на длинную арифметику Задача на «длинную арифметику» Знаете длинную арифметику? Переделать в длинную арифметику Задача на длинную арифметику Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |