[C#] Multidimensional Arrays - 6 задача


8

Здравейте,

Може ли някой да помогне със 6 задача, която очевидно е най-трудната в темата:

6.* Write a class Matrix, to holds a matrix of integers. Overload the operators for adding, subtracting and multiplying of matrices, indexer for accessing the matrix content and ToString().

Имам някакви познания за класове, но не са ми достатъчни, затова бих помолил за всякакви допълнителни материали по темата или пък решение с обяснения, въобще всякакви hint-ове са добре дошли.

Разгледах лекциите от академията за дефиниране и ползване на класове и обекти, но не намерих това, което търся. Чичко Google този път не ми е пръв приятел също.

Смятам, че темата би била полезна не само на мен, ами и на всички, които имат затруднение с тази задача.

Благодаря!




Отговори



13

След кратко търсене за "operator overloading C#", ето моето решение: sourceНямам претенции да е добре написано, но работи.

MSDN: Operator Overloading Tutorial.


от jasssonpet (6814 точки)


3

Примерна реализация на класа Matrics

http://pastebin.com/1F76G1Bc

Идеята е че създаваш, клас, които прави матрица, и съдържа предефинирана операцията за Събиране чрез предефинирането на operator + и така за останалите оператори, което се поддържа стандартно.

В примера е даден, само класа, без реалното инстанциране, но то е аналогично.


от Mihail_Petrov (2718 точки)


0
мерси за забележките. този код които пуснах е псевдо код, само да илюстрирам пример в никакъв случай не е заършен.

от Mihail_Petrov (2718 точки)


0

Ето моето решение: http://pastebin.com/CCyeQCXM


от zlatkov (580 точки)


8
Много ми хареса тази задачка. До сега само бях виждал в дефинициите на готовите класове с F12 как се дефинират операторите, но сега като го видях и на практика как става смятам че беше доста полезно.
Ето и моето решение:
http://pastebin.com/iU2Y0Wqt
Разбира се е доста подобно на другите решения и все пак мисля че има някои малки разлики. Към операциите събиране, изваждане и умножение съм направил проверка за размерностите на матриците и хвърлям изключение ако има проблем с размерите (при събиране и изваждане дименсиите на двете матрици трябва да са равни, а при умножението броя колони на първата матрица трябва да е равен на броя редове на втората). Полетата на класа matrix, rows, columns са private, за да може да са достъпни единствено през публичното свойство Value, което съответно се ползва и от конструкторите и операторите. По този начин си гарантирам че няма да стане някаква грешка и някой да промени информацията за броя на редовете примерно без реално да е променил броя на редовете на самата матрица. В Main метода съм направил няколко теста за различните оператори и случаи. Ако някой има нещо неясно по решението ще се радвам да отговоря на въпроси по него. :)
Поздрави!
Деян :)

от d_p_y (712 точки)


0
+1 и от мен. Добре е индексаторът да хвърля изключение, ако индексите не са в рамките на матрицата, както се получава (IndexOutOfRangeException), когато работим със стандартните масиви. Не е лоша идея и да си направим собствен клас за изключенията, които хвърля Matrix, напр. MatrixException : ApplicationException.
using System;
public class MatrixException : ApplicationException { public MatrixException() : base() { }
public MatrixException(string message, Exception innerException) : base(message, innerException) { }
public MatrixException(string message) : this(message, null) { } }
Множественото число на думата matrix е matrices, както някои подобни думи, които идват в английския от латински - vertex, index (тези двете обаче могат по двата начина - vertexes/vertices, indexes/indices) ;-)

от vic.alexiev (2299 точки)

0
Супер, харесаха ми предложенията ти. Досега не бях писал собствен клас за изключения и смятам примерната горна имплементация за много полезна. Приемам и забележките за правописа ;). Бих ти дал и аз +1, но за съжаление за коментарите няма такава опция :)

от d_p_y (712 точки)


5
Това е моето решение: http://pastebin.com/9XxfLgKa
То наподобява най-много това на Деян. Има си пропъртита, има си проверки, хвърля ексепшъни, мисля че съм написал що-годе добра енкапсулация и т.н. Писал съм доста коментари напред-назад, защото имах нужда от тях, понеже задачата си беше едно предизвикателство :)
GL!
Любо

от ljivanov (35 точки)


0
+1 и от мен. Един проблемен конструктор:
public Matrix(int[,] a) { this.a = a; this.rows = a.GetLength(0); this.cols = a.GetLength(1); }
Ако реша да го използвам и имам
int[,] matrix1 = new int[,] { {1, 2}, {2, 1} };
Matrix m1 = new Matrix(matrix1); Console.WriteLine(m1); matrix1[1, 1] = 1000000; Console.WriteLine(m1);
ще мога да модифицирам елементите на матрицата (класа Matrix) през двумерния масив. Причината е, че int[,] е клас и се подава по референция (т.е. данните не се копират на ново място, а просто създаваш още един указател, който пипа на същото място - двумерният масив и обектът от тип Matrix си споделят едни и същи данни). По-добрият вариант е
this.a = (int[,])a.Clone();
Така this.a сочи чисто ново копие (плитко, но за int не е проблем) на двумерния масив (на ново място), което вече не може да се пипа отвън. Разбира се някой може да каже, че точно това е искал да постигне, но мисля, че обикновено не се практикува такова споделяне на обекти (създава главоболия и трудно откриваеми грешки).

от vic.alexiev (2299 точки)


1
Някой може ли да ми помогне с идеята на ToString(). Нещо не мога да разбера какво трябва да прави. Това което си мисля аз е, че примерно матрицата :
1 2 3 4, ако я ToString()-на трябва да ми върне стринга: “1 2 3 4“ ?

от ivivanov (903 точки)


0
ToString() метода е дефиниран в класа object и съответно се наследява от всички останали класове. Той е важен, тъй като доста други методи го използват скрито (например Console.WriteLine(a) извиква скрито а.ToString() и го отпечатва на екрана). В случая за матрицата се иска ти да си предефинираш ToString() метода за твоя клас, за да може когато го принтираш с Console.WriteLine() да речем, той да се отпечатва на конзолата по начинът, който ти смяташ за подходяш за отпечатване на матрицата. Според мен по-подходящ начин за принтиране е тя да се отпечата на n реда с по m елемента във всеки ред, отколкото на 1 ред с m*n елемента. Въпрос на вкус :)

от d_p_y (712 точки)

0
може и да я върнеш и така: {1,2},{3,4}



1

Ето и от мен едно решение

Използвам съм предефинирани оператори, даже и документация съм писал wink. ToString метода връща стринг с формат:
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}




1

Ето и моето решение:

http://pastebin.com/htuSYWRa

1. Създавам клас данни, които съдържат колко реда и колони има матрицата, както и get методи за тях.

2.Създавам indexer за класа (как става това е описано тук)

3. Оверлоадвам операторите с помощта на линка, предостажен от jassonpet. В общи линии за различните операции само се променя един символ. Във всеки оверлоаднат оператор проверявам дали матриците са с еднаква дължина - ако не са се хвърля Exception.

4. Написвам и ToString() метода използвайки StringBuilder.

5. Пълня 2 матрици с някакви данни и ги показвам на екрана. Извършвам всяка от операциите и след нея показвам резултата.


от gallumbits (2371 точки)


2

Здравейте,

Когато преглеждах тази тема преди 1-2 дена, видях, че някои колеги неправилно са използвали формула за умножение на матрици - умножават елемент по елемент, при това операцията не е комутативна, както при умножение на числа. Разсеях се тогава, не написах във форума и сега не помня точно къде беше.

Вярното решение е както на @jasssonpet (избран е за най-добър и погледнах там сега, за по-бързо). Така че ако желаете, прегледайте си решенията, корекцията не изисква много усилия.

Ще отворя една скоба,за да кажа, че за да бъде възможно умножението на две матрици, е необходимо броят на колоните на първата да бъде равен на броя на редовете на втората. Тъй като задачата включва и овърлоуд на сума и изваждане, а там пък изискването е да имат еднакъв брой на редовете и колоните съотв., в моето решение допуснах, че работим с квадратни матрици.

Поздрав :-)


от ellapt (6303 точки)


0
http://pastebin.com/RWPqTRg8 Kлас Matrix
http://pastebin.com/Q5SjPk1W - Демо за +/-/* и другите работи

от Rokata (397 точки)


0

Подобно на останалите колеги си създавам клас Matrix, в който се дефинират търсените операции и в тези методи се имплементира с цикли кода http://pastebin.com/7y2EWZee


от AsenVal (3487 точки)


0
Съвет.. веднага разкарай тоя стринг в ToString() и го замени със StringBuilder/StringBuffer/Object или каквото още ти хрумне, всеки пък щом прибавяш нещо на "str" ти прави нов стринг с нова памет и пази предходните, да предположим ще добавяш или редактираш нещо по променливата 100 пъти, еми имаш 100 нови променливи, сочещи към различни адреси в паметта.
п.с. string is immutable

от Prophian (1234 точки)

0
Ок мерси за коментара, от вчера вече знам за това, че стринга е бавен, но това не означава, че стрингвовете вече са забранени за ползване. Да в някой случай когато преценя, че би било по-полезно да е със StringBuilder го правя с него в останалите случай string си оставя незаменяем.

от AsenVal (3487 точки)