пятница, 22 февраля 2013 г.

Сложение больших чисел C#.

Здравствуйте, сегодня мы будем работать с большими числами.
С такими, количество символов в которых превышает 10 000!

Для  примера рассмотрим следующую задачу:

Write a method that adds two positive integer numbers represented as arrays of digits (each array element arr[i] contains a digit; the last digit is kept in arr[0]). Each of the numbers that will be added could have up to 10 000 digits.

Требовалась реализация на C#. Для решения данной интересной задачки был создан класс BigNumber, числа представляются в виде массивов типа int, размеры массивов генерируются в случайном порядке, от 10 000 до 100 000 элементов, инициализацией массивов занимается
конструктор, из исходного кода конструктора всё становится ясным. массивы, в которых хранятся числа, являются закрытыми от внешнего мира модификатором private. Для работы с ними применяются публичные поля. Для операции сложения чисел мы будем хранить число в массиве записанным в обратном порядке. Массивы, то есть наши числа могут быть разной длины, поэтому Нам надо позаботиться об этом. В конструкторе мы создадим массивы, которые будут содержать одинаковое количество символов,

this.firstNumber = new int[maxSize];
this.secondNumber = new int[maxSize];

 
...просто недостающие, то есть непроинициализированные ячейки одного из массивов будут автоматически проинициализированы значением "0"

Основная работа программы выпадает на метод public void AddNumbers(), который, как Вы уже и догадались, складывает числа, возвращая результат сложения.

Сложение чисел производится столбиком, только необходимо всегда проверять, какое мы число получаем: из одного или двух цифр. Также проверяется, не с последним ли мы элементом массива имеем дело. К коду метода предоставлены достаточно подробные комментарии, поэтому, как мне кажется, расписывать подробнее еще раз тут нет смысла.

Выводом результатов заведует метод public void AdditionResultTxt(). Данный метод переворачивает массив (помните, что мы работали с числами, записанными задом на перед?), а потом выводит результат в текстовый файл.

Тестирование класса тривиальное, просто создаём объект bg класса BigNumbers, потом вызываем метод AddNumbers(), для вывода результатов сложения чисел вызовем следующий метод: bg.AdditionResultTxt().
 Всё! Наслаждайтесь своим супербольшим числом!

Здесь Вы можете скачать исходный код проекта.
 
Результат работы программы по сложению больших чисел.
 
Исправления и дополнения только приветствуются! 

 
Исходный код программы для сложения больших чисел.
 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
 
namespace BigNumbers
{
    public class BigNumber
    {
        int[] firstNumber;
        int[] secondNumber;
        int[] resultNumber;
 
        public BigNumber()
        {
            //константы для случайной генерации размеров массивов
            const int FROM = 10000; //10 000
            const int TO =  100000;//100 000
 
            Random rand = new Random();
            int firstNumberSize = rand.Next(from, to);
            int secondNumberSize = rand.Next(from, to);
 
            //получаем максимальный размер массива
            int maxSize = Math.Max(firstNumberSize, secondNumberSize);
 
            this.firstNumber = new int[maxSize];
            this.secondNumber = new int[maxSize];
 
            //инициализируем массивы случайными числами
            for (int i = 0; i < firstNumberSize; i++)
            {
                firstNumber[i] = rand.Next(0, 9);
            }
 
            for (int i = 0; i < secondNumberSize; i++)
            {
                secondNumber[i] = rand.Next(0, 9);
            }
        }
 
        public int[] FirstNumberValue
        {
            get { return this.firstNumber; }
        }
 
        public int[] SecondNumberValue
        {
            get { return this.secondNumber; }
        }
 
        public int[] AdditionResult
        {
            get { return this.resultNumber; }
 
        }
 
        /// <summary>
        /// метод для записи результата сложения двух длинных чисел в текстовый файл
        /// </summary>
        public void AdditionResultTxt()
        {
            StreamWriter sw = new StreamWriter("addition_result.txt");
            sw.WriteLine("The result of addition of {0}-digit numbers", firstNumber.Length);
 
            for (int i = resultNumber.Length-1; i >= 0; i--)
            {
                sw.Write(resultNumber[i]);
            }
            sw.Close();
        }
 
        /// <summary>
        /// метод для сложения двух длинных чисел
        /// </summary>
        public void AddNumbers()
        {
            int lastNumber = 0; // последнее число в массиве (первое в числе)
 
           //массивы все приведены к одинаковой длине, складываем столбиком
           for (int i = 0; i < firstNumber.Length; i++)
            {
               //если сумма цифр не больше десяти
                if (firstNumber[i] + secondNumber[i] < 10)
                {
                    //складываем их без проблем
                    firstNumber[i] += secondNumber[i];
                }
 
                //если мы получили двузначное число (10, 12, 17)
                else 
                {
                    //смотрим, не последний ли элемент массива, в котором получилась такая сумма
                    //если не последний, то...
                    if (i + 1 < firstNumber.Length)
                    {
                        //сохраняем в нем младший разряд числа (было 12 - останется 2, было 18 - останется 8)
                        firstNumber[i] = firstNumber[i] + secondNumber[i] - 10;
 
                        //в следующий элемент массива переносим запомненный разряд, т.е. единицу
                        firstNumber[i + 1] += 1;
                    }
 
                    //если мы в последнем элементе массива, то нам нужно работать только с ним, следующего ведь нет
                    else
                    {
                        //складываем элементы массивов
                        if (firstNumber[i] + secondNumber[i] < 10)
                        {
                            firstNumber[i] = firstNumber[i] + secondNumber[i];
                        }
                        else 
                        {
                            firstNumber[i] = firstNumber[i] + secondNumber[i] - 10;
                            lastNumber = 1;
                        }
 
                    }
                }
            }
 
            //сохраняем результат
           SetResult(lastNumber);
        }
 
        /// <summary>
        /// метод для инициализации массива с результатом сложения
        /// </summary>
        private void SetResult( int lastNumber)
        {
            switch (lastNumber)
            { 
                case 0:
                    this.resultNumber = firstNumber;
                    break;
 
                case 1:
                    resultNumber = new int[firstNumber.Length + 1];
                    resultNumber[firstNumber.Length] = lastNumber;
 
                    for (int i = 0; i < firstNumber.Length; i++)
                    {
                        resultNumber[i] = firstNumber[i];
                    }
                    break;
            }
        }
    }
 
 
    class Program
    {
        static void Main(string[] args)
        {
 
            BigNumber bg = new BigNumber();
            bg.AddNumbers();
            bg.AdditionResultTxt();
 
            Console.WriteLine("The result of addition was successfully written in 'addition_result.txt'");
            Console.ReadKey();
        }
    }
}
 

Комментариев нет:

Отправить комментарий