Swift matrix sum

2019-02-20 14:28发布

I'm trying to develop a func which allows to sum two matrix if they are equals to the same dimension, but I get an error "EXC_BAD_INSTRUCTION" on the try.

Here is my Playground:

import Foundation

enum RisedError: ErrorType {
    case DimensionNotEquals
    case Obvious(String)
}

func ==(lhs: Matrix, rhs: Matrix) -> Bool {
    return (lhs.rows) == (rhs.rows) && (lhs.columns) == (rhs.columns)
}

protocol Operation {
    mutating func sumWith(matrixB: Matrix) throws -> Matrix
}

struct Matrix {
    let rows: Int, columns: Int
    var grid: [Double]
    init(rows: Int, columns: Int) {
        self.rows = rows
        self.columns = columns
        grid = Array(count: rows * columns, repeatedValue: 0.0)
    }
    func indexIsValidForRow(row: Int, column: Int) -> Bool {
        return row >= 0 && row < rows && column >= 0 && column < columns
    }
    subscript(row: Int, column: Int) -> Double {
        get {
            assert(indexIsValidForRow(row, column: column), "Index out of range")
            return grid[(row * columns) + column]
        }
        set {
            assert(indexIsValidForRow(row, column: column), "Index out of range")
            grid[(row * columns) + column] = newValue
        }
    }
}

var matrixA = Matrix(rows: 2, columns: 2)
matrixA[0,0] = 1.0
matrixA[0,1] = 2.0
matrixA[1,0] = 3.0
matrixA[1,1] = 4.0
var matrixB = Matrix(rows: 2, columns: 2)
matrixB[0,0] = 5.0
matrixB[0,1] = 6.0
matrixB[1,0] = 7.0
matrixB[1,1] = 8.0

print(matrixA)
print(matrixB)

extension Matrix: Operation {

    mutating func sumWith(matrixB: Matrix) throws -> Matrix {

        guard self == matrixB else { throw RisedError.DimensionNotEquals }

        for row in 0...self.rows {
            for column in 0...self.columns {
                self[row, column] = matrixB[row, column] + self[row, column]
            }
        }
        return self
    }
}

do {
    try matrixA.sumWith(matrixB)
} catch RisedError.DimensionNotEquals {
    print("The two matrix's dimensions aren't equals")
} catch {
    print("Something very bad happens")
}

Here is the error Log:

enter image description here

标签: swift matrix sum
3条回答
Bombasti
2楼-- · 2019-02-20 15:12

Actually your error is Index out of range

Replace your extension with this code.

extension Matrix: Operation {

    mutating func sumWith(matrixB: Matrix) throws -> Matrix {

        guard self == matrixB else { throw RisedError.DimensionNotEquals }

        for row in 0...self.rows - 1 {
            for column in 0...self.columns - 1 {
                self[row, column] = matrixB[row, column] + self[row, column]
            }
         }
        return self
    }
}

Hope it would solve your problem.

查看更多
The star\"
3楼-- · 2019-02-20 15:14
swift 4 - Addition 0f 3 x 3 Matrices

enum RisedError: Error {
        case DimensionNotEquals
        case Obvious(String)
    }
    func ==(lhs: Matrix, rhs: Matrix) -> Bool {
        return (lhs.rows) == (rhs.rows) && (lhs.columns) == (rhs.columns)
    }
    protocol Operation {
        mutating func sumWith(matrixB: Matrix) throws -> Matrix

    }
    class ViewController: UIViewController {


    //Matrix creation
        func matrixCreation(){
            var matrixA = Matrix(rows: 3, columns: 3)
            var matrixB = Matrix(rows: 3, columns: 3)
            matrixA[0,0] = 1.0
            matrixA[0, 1] = 2.0
            matrixA[0, 2] = 2.0
            matrixA[1, 0] = 3.0
            matrixA[1, 1] = 4.0
            matrixA[1, 2] = 4.0
            matrixA[2, 0] = 1.0
            matrixA[2, 1] = 1.0
            matrixA[2, 2] = 1.0
            matrixB[0,0] = 5.0
            matrixB[0, 1] = 6.0
            matrixB[0, 2] = 6.0
            matrixB[1, 0] = 7.0
            matrixB[1, 1] = 8.0
            matrixB[1, 2] = 8.0
            matrixB[2, 0] = 1.0
            matrixB[2, 1] = 1.0
            matrixB[2, 2] = 1.0

            var outputMartix = Matrix(rows: 3, columns: 3)
            print(matrixB , matrixA)
            do {
                outputMartix = try! matrixA.sumWith(matrixB: matrixB)
                print(outputMartix)
            }catch RisedError.DimensionNotEquals{
                print("Dimensions are not equal")

            }
        }

    }

    //Matrix Configuration

    struct Matrix {
        let rows: Int, columns: Int
        var grid: [Double]
        init(rows: Int, columns: Int) {
            self.rows = rows
            self.columns = columns
            grid = Array(repeating: 0.0, count: rows * columns)
        }
        func indexIsValidForRow(row: Int, column: Int) -> Bool {
            return row >= 0 && row < rows && column >= 0 && column < columns
        }
        subscript(row: Int, column: Int) -> Double {
            get {
                assert(indexIsValidForRow(row: row, column: column), "Index out of range")
                return grid[(row * columns) + column]
            }
            set {
                assert(indexIsValidForRow(row: row, column: column), "Index out of range")
                grid[(row * columns) + column] = newValue
            }
        }
    }
    extension Matrix: Operation {

        mutating func sumWith(matrixB: Matrix) throws -> Matrix {

            guard self == matrixB else { throw RisedError.DimensionNotEquals }

            for row in 0...self.rows - 1 {
                for column in 0...self.columns - 1 {
                    self[row, column] = matrixB[row, column] + self[row, column]
                }
            }
            return self
        }
    }
查看更多
仙女界的扛把子
4楼-- · 2019-02-20 15:22

The problem is you're using the closed range operator in your for loop 0...self.rows. This will include the upper bound of the range in the iteration, which in your case is out of bounds and will therefore crash.

You want to use the half-open range operator ..< instead:

for row in 0..<self.rows {
    for column in 0..<self.columns {
        self[row, column] = matrixB[row, column] + self[row, column]
    }
}

This will iterate up to but not including the upper bound.


I would also note @MartinR's comment above – defining equality for the matrices to be solely based on the dimensions being the same seems illogical. Remember that equality implies substitutability (i.e if a == b, a and b are interchangeable).

I would consider changing your == to check both dimensions and values, and then implement your own dimension check in your sumWith method (or create a new method to compare dimensions).

查看更多
登录 后发表回答