Матричное умножение в Objective-C - PullRequest
0 голосов
/ 09 февраля 2012

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

+ (NSMutableArray *)arrayOfWidth:(NSInteger)width andHeight:(NSInteger)height {
    return [[self alloc] initWithWidth:width andHeight:height];
}

- (id)initWithWidth:(NSInteger)width andHeight:(NSInteger)height {
    if((self = [self initWithCapacity:height])) {
        for(int i = 0; i < height; i++) {
            NSMutableArray *inner = [[NSMutableArray alloc] initWithCapacity:width];
            [self addObject:inner];
        }
    }
    return self;
}

+ (NSMutableArray *)matrixA:(NSMutableArray *)matrixA multiplyMatrixB:(NSMutableArray *)matrixB {
    int aRow = [matrixA count];
    int aColumn = [[matrixA objectAtIndex:0] count];
    int bRow = [matrixB count];
    int bColumn = [[matrixB objectAtIndex:0] count];
    NSMutableArray *newArray = [NSMutableArray arrayOfWidth:aRow andHeight:bColumn];

    for (int i = 0; i < aRow; i++) {
        for (int j = 0; j < bColumn; j++) {
            double sum = 0.0;
            for (int k = 0; k < aColumn; k++) {
                NSMutableArray *innerA = [matrixA objectAtIndex:i];
                double numA = [[innerA objectAtIndex:k] doubleValue];
                NSMutableArray * innerB = [matrixB objectAtIndex:k];
                double numB = [[innerB objectAtIndex:j] doubleValue];
                sum += numA * numB; 
            }
            NSNumber *result = [NSNumber numberWithDouble:sum];
            [[newArray objectAtIndex:i] insertObject:result atIndex:j];
        }
    }
    return newArray;
}

Что-то не так с кодом? И как я могу это исправить?


    //First, I create a array to hold the numbers
    NSNumber *num11 = [NSNumber numberWithDouble:-2.0];
    NSNumber *num12 = [NSNumber numberWithDouble:1.0];
    NSNumber *num13 = [NSNumber numberWithDouble:-1.0];
    NSNumber *num14 = [NSNumber numberWithDouble:2.0];
    NSNumber *num21 = [NSNumber numberWithDouble:-7.0];
    NSNumber *num22 = [NSNumber numberWithDouble:0.0];
    NSNumber *num23 = [NSNumber numberWithDouble:-1.0];
    NSNumber *num24 = [NSNumber numberWithDouble:-4.0];
    NSNumber *num31 = [NSNumber numberWithDouble:-2.0];
    NSNumber *num32 = [NSNumber numberWithDouble:-1.0];
    NSNumber *num33 = [NSNumber numberWithDouble:0.0];
    NSNumber *num34 = [NSNumber numberWithDouble:-2.0];
    NSNumber *num41 = [NSNumber numberWithDouble:-3.0];
    NSNumber *num42 = [NSNumber numberWithDouble:-2.0];
    NSNumber *num43 = [NSNumber numberWithDouble:0.0];
    NSNumber *num44 = [NSNumber numberWithDouble:-3.0];

    NSMutableArray *temp = [NSMutableArray arrayWithObjects:num11, num12, num13, num14, num21, num22, num23, num24, num31, num32, num33, num34, num41, num42, num43, num44, nil];

    //Second, I create the matrix and get the elements from that array 
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            double c = [[temp objectAtIndex:4*i+j] doubleValue];
            NSNumber *object = [NSNumber numberWithDouble:c];
            [[matrix objectAtIndex:i] insertObject:object atIndex:j];
        }
    }

    //Then, I do the multiplication for matrix and itself
    NSMutableArray *multiMatrix = [NSMutableArray matrixA:matrix multiplyMatrixB:matrix];

    //get all the elements from the multiMatrix
    double m11 = [[[multiMatrix objectAtIndex:0] objectAtIndex:0] doubleValue];
    double m12 = [[[multiMatrix objectAtIndex:0] objectAtIndex:1] doubleValue];
    double m13 = [[[multiMatrix objectAtIndex:0] objectAtIndex:2] doubleValue];
    double m14 = [[[multiMatrix objectAtIndex:0] objectAtIndex:3] doubleValue];

    double m21 = [[[multiMatrix objectAtIndex:1] objectAtIndex:0] doubleValue];
    double m22 = [[[multiMatrix objectAtIndex:1] objectAtIndex:1] doubleValue];
    double m23 = [[[multiMatrix objectAtIndex:1] objectAtIndex:2] doubleValue];
    double m24 = [[[multiMatrix objectAtIndex:1] objectAtIndex:3] doubleValue];

    double m31 = [[[multiMatrix objectAtIndex:2] objectAtIndex:0] doubleValue];
    double m32 = [[[multiMatrix objectAtIndex:2] objectAtIndex:1] doubleValue];
    double m33 = [[[multiMatrix objectAtIndex:2] objectAtIndex:2] doubleValue];
    double m34 = [[[multiMatrix objectAtIndex:2] objectAtIndex:3] doubleValue];

    double m41 = [[[multiMatrix objectAtIndex:3] objectAtIndex:0] doubleValue];
    double m42 = [[[multiMatrix objectAtIndex:3] objectAtIndex:1] doubleValue];
    double m43 = [[[multiMatrix objectAtIndex:3] objectAtIndex:2] doubleValue];
    double m44 = [[[multiMatrix objectAtIndex:3] objectAtIndex:3] doubleValue];

    //Or you can use the NSLog to check the result 
    NSString *lineOne = [NSString stringWithFormat:@"%f, %f, %f, %f", m11, m12, m13, m14];
    NSString *lineTwo= [NSString stringWithFormat:@"%f, %f, %f, %f", m21, m22, m23, m24];
    NSString *lineThree = [NSString stringWithFormat:@"%f, %f, %f, %f", m31, m32, m33, m34];
    NSString *lineFour = [NSString stringWithFormat:@"%f, %f, %f, %f", m41, m42, m43, m44];

@ на крыше, вот и весь код

Ответы [ 3 ]

6 голосов
/ 12 февраля 2012

Если вы используете iOS, вы можете рассмотреть матричные процедуры в GLKit

2 голосов
/ 11 февраля 2012

Если вы знакомы с векторными операциями MATLAB (даже если не знакомы), я бы порекомендовал вам проверить Accelerate Framework , это оптимизированная среда для цифровой обработки сигналов.

Два больших преимущества:

  • У них уже реализована эта операция.
  • Это более эффективный способ сделать это, но, очевидно, не для маленьких матриц, см.комментарии для более подробной информации.

Вероятно, это функция, которую вы ищете:

vDSP_mmul : выполняет неуместное умножение двух матриц;с одинарной точностью.

void vDSP_mmul (
   float *__vDSP_a,
   vDSP_Stride __vDSP_aStride,
   float *__vDSP_b,
   vDSP_Stride __vDSP_bStride,
   float *__vDSP_c,
   vDSP_Stride __vDSP_cStride,
   vDSP_Length __vDSP_M,
   vDSP_Length __vDSP_N,
   vDSP_Length __vDSP_P
);
Parameters
__vDSP_a
Input matrix A.
__vDSP_aStride
The stride within __vDSP_a. For example if stride is 2, every second element is used.
__vDSP_b
Input matrix B.
__vDSP_bStride
The stride within __vDSP_b. For example if stride is 2, every second element is used.
__vDSP_c
The result matrix.
__vDSP_M
The number of rows in matrix A.
__vDSP_N
The number of columns in matrix B.
__vDSP_P
The number of columns in matrix A and the number of rows in matrix B.
Discussion
This function multiplies an M-by-P matrix (A) by a P-by-N matrix (B) and stores the results in an M-by-N matrix (C).

Выполняет следующую операцию:

С другой стороны, если написание метода является обязательным требованием, этот пост вам вообще не поможет.

0 голосов
/ 29 июня 2017

Здесь в основном две ошибки:

  1. В основной программе вы не объявили matrix. Вы знаете, как решить эту проблему.
  2. Когда вы создаете matrix, если вы уже инициализировали матрицу нулями, insertingObject создаст матрицу размером «4x8», а не «4x4».

    [[matrix objectAtIndex:i] insertObject:object atIndex:j];
    
  3. В вашем методе умножения матриц вы также insertObject превращаетесь в существующую матрицу, делая ее размер «4x8» вместо «4x4».

Чтобы решить эту вторую проблему, вам нужно заменить метод insertObject:atIndex на replaceObjectAtIndex:withObject.

Это должно решить проблему.

...