2012-02-09 84 views
0

這些是我在我的項目中進行矩陣計算的一些代碼。
它們是兩個類方法和一個實例方法,用於創建矩陣並進行矩陣乘法運算。
矩陣乘法的方法效果不好,它的結果是錯誤的。Objective-C中的矩陣乘法

+ (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]; 

@rooftop,這是所有的代碼

+1

該方法的「錯誤」是什麼?你使用它會得到什麼結果?你在期待什麼?你如何調用該方法?你真的需要提供更多信息。 – rooftop 2012-02-09 16:54:15

+2

這是否需要使用可可來完成?我在這裏冒險,猜測你使用的是iOS或OS X:兩者都有[Accelerate.framework](https://developer.apple.com/library/mac/#documentation/Accelerate/Reference /AccelerateFWRef/_index.html),它有很多(非常快!)矩陣乘法支持。 – 2012-02-10 05:15:07

+1

在ObjC中這樣做的任何理由?在C數組中表達這個要比在NSMutableArray中容易得多。我建議從2×2陣列開始,逐步通過數學來查看你的bug在哪裏。 – 2012-02-10 20:34:51

回答

2

如果您熟悉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). 

此執行以下操作:

另一方面,如果寫自己有要求的方法,這個帖子不會幫你的。

+1

這絕對不總是更有效率。最近我一直在測試加速,對於各種各樣的矩陣,特別是像海報這樣的小矩陣,它比手寫代碼要慢得多(速度慢3-4倍)。對於它的擅長,這是非常棒的,但它並不總是一個表現勝利。請參閱http://stackoverflow.com/questions/3950383/ios-4-accelerate-cblas-with-4x4-matrices/5197634#comment11586218_5197634 – 2012-02-10 20:20:27

+0

不知道,謝謝你的擡頭,我已經添加了一些評論發表在你的帖子中的評論。 :D – 2012-02-10 20:22:01

6

如果你在iOS上,你可能要考慮矩陣例程GLKit

0

主要有兩種錯誤的位置:

  1. 在主程序中,你沒有申報matrix。你知道如何解決這個問題。
  2. 在創建matrix時,如果您已將矩陣初始化爲零,insertingObject將使矩陣的大小爲'4x8',而不是'4x4'。

    [[matrix objectAtIndex:i] insertObject:object atIndex:j]; 
    
  3. 在你的矩陣乘法的方法,你也insertObject到現有的矩陣,使得它的大小,而不是「4×4」×8'。

要解決此第二個問題,你需要更換方法insertObject:atIndex,與replaceObjectAtIndex:withObject

這應該解決的問題。

+0

謝謝你。我試圖使用傳統的格式,但它不是正確的。 – 2017-06-29 22:21:56