Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Арифметические операции для классов с обобщенным т, Арифметические операции для Т и Т 
:(
    Опции темы
eloiss
Дата 31.5.2017, 00:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Доброго времени!

Никак не могу разобраться в проблеме и прошу помощи и совета у авторитетных гуру!

Суть в следующем. Есть класс Matrix - поддерживает операции с матрицами и т.д. Класс объявлен как:
Код

Class Matrix<T> where T: struct

что позволяет хранить в матрице значения разных типов

Имеется также перегруженный оператор сложения

Код

        /// <summary>
        /// Сложение двух матриц
        /// </summary>
        /// <param name="M1">Матрица - первое слагаемое</param>
        /// <param name="M2">Матрица - второе слагаемое</param>
        /// <returns>Матрица - сумма</returns>       
        public static Matrix<T> operator + (Matrix<T> M1, Matrix<T> M2)
        {
            if (ReferenceEquals(M1, null) || ReferenceEquals(M2, null))
                throw new InvalidOperationException(String.Format("[ID:{0},{1}] -> Не создан один из операндов операции!", M1.ID, M2.ID));
 
            Matrix<T> ret_val = new Matrix<T>(M1.Width, M1.Height, null);
            try
            {
                if (!M1.CanAdd(M2))
                {
                    throw new ArgumentException(String.Format("[ID:{0},{1}] -> Невозможно выполнить указанную операцию!", M1.ID, M2.ID));
                }
                else
                {
                    for (int r = 0; r < M1.Height; r++)
                        for (int c = 0; c < M1.Width; c++)
                            ret_val[r, c] = M1[r, c] + M2[r, c];
                }
            }
            catch (ArgumentException aex) { Log.AddString(aex.Message); }
            catch (Exception ex){ Log.AddString(ex.Message); }
            // возврат
            return ret_val;
        }


Но компилятор ругается на строку
Код

ret_val[r, c] = M1[r, c] + M2[r, c];

, дескать, невозможно совершить операцию + между типами Т и Т.

Отсюда вопрос:
1. Почему в данном случае не работает ограничение
Код

where T: struct


2. Какой есть выход из ситуации - третий день бьюсь, но похоже отсутствие достаточного количества мозгов не позволяет ничего придумать

Задача дополняется наличием структуры типа Fraction (дробь), в которой также переопределены арифметические операторы.
При этом T должен поддерживать тип Fraction

Код дроби:
Код

        #region "Fraction"
        /// <summary>
        /// Структура представления рациональной дроби
        /// nominator - числитель дроби
        /// denominator - знаменатель дроби
        /// reducable - Флаг немедленного сокращения дроби-результата выполнения арифметических операций
        /// </summary>
        public struct Fraction
        {
            private int nominator;
            public int Nominator { get { return nominator; } }
            private int denominator;
            public int Denominator { get { return denominator; } }
            private static bool reducable;
            public static bool Reducable { get { return reducable; } set { reducable = value; } }
 
            /// <summary>
            /// Конструктор по целому значению
            /// </summary>
            /// <param name="Value">Целое число, которое будет числителем дроби (знаменатель=1)</param>
            public Fraction(int Value)
            {
                nominator = Value;
                denominator = 1;
            }
            
            /// <summary>
            /// Конструктор по числителю и знаменателю
            /// </summary>
            /// <param name="Nom">Устанавливает числитель дроби</param>
            /// <param name="Denom">Устанавливает знаменатель дроби</param>
            public Fraction(int Nom, int Denom)
            {
                if (Denom == 0)
                {
                    nominator = 0;
                    denominator = 1;
                    throw new ArgumentException("Знаменатель дроби не может быть нулевым!");
                }
                else
                {
                    nominator = Nom;
                    denominator = Denom;
                }
            }
            
            /// <summary>
            /// Конструктор копирования дроби
            /// </summary>
            /// <param name="F">Копирует числитель и знаменатель из указанной дроби F</param>
            public Fraction(Fraction F)
            {
                nominator = F.nominator;
                denominator = F.denominator;
            }
            
            /// <summary>
            /// Переопределение стандартного вывода дроби в виде строки
            /// </summary>
            /// <returns>Строка в формате n/d</returns>
            public override string ToString()
            {
                return String.Format("{0}/{1}", nominator, denominator);
            }
            
            /// <summary>
            /// Декомпозиция дроби
            /// В результате декомпозиции дробь становиться правильной (целая часть отсекается и возвращается как результат
            /// </summary>
            /// <returns>Целая часть дроби</returns>
            public int Decompose()
            {
                int ret_val = (nominator - nominator % denominator) / denominator;
                nominator = nominator % denominator;
                return ret_val;
            }
            
            /// <summary>
            /// Сокращение дроби (деление числителя и знаменателя на НОД)
            /// </summary>
            public void Reduce()
            {
                for (int i = nominator > denominator ? nominator : denominator;
                         i >1; i--)
                {
                    if (nominator % i == 0 && denominator % i == 0)
                    {
                        nominator /= i;
                        denominator /= i;
                        break;
                    }
                }
            }
 
            /// <summary>
            /// Проведение операции сложения двух дробей
            /// </summary>
            /// <param name="F1">Первое слагаемое</param>
            /// <param name="F2">Второе слагаемое</param>
            /// <returns>Результат сложения двух дробей (результат будет сокращен, если установлено свойство Reducable)</returns>
            public static Fraction operator +(Fraction F1, Fraction F2)
            {
                Fraction ret_val = new Fraction();
                if (F1.denominator == F2.denominator)
                {
                    ret_val.denominator = F1.denominator;
                    ret_val.nominator = F1.nominator + F2.nominator;
                }
                else
                {
                    ret_val.denominator = F1.denominator * F2.denominator;
                    ret_val.nominator = F1.nominator * F2.denominator + F2.nominator * F1.denominator;
                }
                // reduce
                if(reducable) ret_val.Reduce();
                // return
                return ret_val;
            }
 
            /// <summary>
            /// Проведение операции вычитания двух дробей
            /// </summary>
            /// <param name="F1">Уменьшаемое</param>
            /// <param name="F2">Вычитаемое</param>
            /// <returns>Результат вычитания двух дробей (результат будет сокращен, если установлено свойство Reducable)</returns>
            public static Fraction operator -(Fraction F1, Fraction F2)
            {
                Fraction ret_val = new Fraction();
                if (F1.denominator == F2.denominator)
                {
                    ret_val.denominator = F1.denominator;
                    ret_val.nominator = F1.nominator - F2.nominator;
                }
                else
                {
                    ret_val.denominator = F1.denominator * F2.denominator;
                    ret_val.nominator = F1.nominator * F2.denominator - F2.nominator * F1.denominator;
                }
                // reduce
                if (reducable) ret_val.Reduce();
                // return
                return ret_val;
            }
 
            /// <summary>
            /// Проведение операции умножения двух дробей
            /// </summary>
            /// <param name="F1">Первый множитель</param>
            /// <param name="F2">Второй множитель</param>
            /// <returns>Результат умножения двух дробей (результат будет сокращен, если установлено свойство Reducable)</returns>
            public static Fraction operator *(Fraction F1, Fraction F2)
            {
                Fraction ret_val = new Fraction();
                ret_val.denominator = F1.denominator * F2.denominator;
                ret_val.nominator = F1.nominator * F2.nominator;
                // reduce
                if (reducable) ret_val.Reduce();
                // return
                return ret_val;
            }
 
            /// <summary>
            /// Проведение операции деления двух дробей
            /// </summary>
            /// <param name="F1">Делимое/param>
            /// <param name="F2">Делитель</param>
            /// <returns>Результат деления двух дробей (результат будет сокращен, если установлено свойство Reducable)</returns>
            public static Fraction operator /(Fraction F1, Fraction F2)
            {
                Fraction ret_val = new Fraction();
                ret_val.nominator = F1.nominator * F2.denominator;
                ret_val.denominator = F1.denominator * F2.nominator;
                // reduce
                if (reducable) ret_val.Reduce();
                // return
                return ret_val;
            }
 
            /// <summary>
            /// Неявное преобразование целого числа в дробь
            /// </summary>
            /// <param name="Val">Целое число для преобразования</param>
            /// <returns>Возвращаемая дробь, числителем которой является Val, а знаменателем - 1</returns>
            public static implicit operator Fraction(int Val)
            {
                Fraction F = new Fraction(Val);
                return F;
            }
 
            /// <summary>
            /// Явное преобразование дроби в целое число
            /// </summary>
            /// <param name="F">Дробь для преобразования</param>
            /// <returns>Возвращаемое значение - целая часть дроби</returns>
            public static explicit operator int(Fraction F)
            {
                return F.Decompose();
            }
 
            /// <summary>
            /// Явное преобразование дроби в число с плавающей точкой
            /// </summary>
            /// <param name="F">Дробь для преобразования</param>
            /// <returns>Возвращаемое значение - вычисленная дробь в десятичном формате с плавающей точкой</returns>
            public static explicit operator double(Fraction F)
            {
                double ret_val;
                ret_val = (double)F.nominator / (double)F.denominator;
                return ret_val;
            }
        }
        #endregion


Но сейчас пока главное разобраться как реализовать арифметику для Т и Т



PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


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

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


 




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


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

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