簡體   English   中英

在2D數組中分配值

[英]Assigning values in a 2D array

我在Rust中編寫了一些代碼(主要是作為POC)。 代碼采用2D數組,將其傳遞給第二個函數進行一些矩陣數學運算(我知道有一個標准庫可以做到這一點,但我想習慣事情的運作方式)。

問題是對2D陣列的分配導致了問題。

我的代碼看起來像這樣

fn main() 
{
    // first create a couple of arrays - these will be used
    // for the vectors
    let line1: [i32; 4] = [4, 2, 3, 3];
    let line2: [i32; 4] = [3, 4, 5, 7];
    let line3: [i32; 4] = [2, 9, 6, 2];
    let line4: [i32; 4] = [5, 7, 2, 4];

    // create two holding arrays and assign
    let array_one = [line1, line3, line4, line2];
    let array_two = [line2, line1, line3, line4];

    // let's do the multiply
    let result = matrix_multiply(&array_one, &array_two);
    println!("{:?}", result);
}

fn matrix_multiply(vec1:&[&[i32;4];4], vec2:&[&[i32;4];4]) -> [[i32; 4];4]
{
    // we need to deference the parameters passed in
    let vec_one:[[i32;4];4] = vec1;
    let vec_two:[[i32;4];4] = vec2;

    // we need to store the sum
    let mut sum = 0;

    // we need to create the arrays to put the results into
    let mut result = [[0i32; 4]; 4];

    // loop through the two vectors
    for vone in 0..4
    {
        for vtwo in 0..4
        {
            for k in 0..4
            {
                sum = sum + vec1[[vone].k] * vec2[[k].vtwo];
            }
            result[[vec_one].vec_two] = sum;
            sum = 0;
        }
   }

   return result;
}

我也試過result[vec_one][vec_two] = sum但是當我來編譯時,看起來分配給數組有問題。

我在這做錯了什么?

這是你的錯誤,我相信(至少其中一個):

<anon>:15:34: 15:44 error: mismatched types:
 expected `&[&[i32; 4]; 4]`,
    found `&[[i32; 4]; 4]`
(expected &-ptr,
    found array of 4 elements) [E0308]
<anon>:15     let result = matrix_multiply(&array_one, &array_two);
                                           ^~~~~~~~~~

問題是,數組的引用或取消引用不能在它們的嵌套的多個層次上進行。 這是因為[&[i32; 4]; 4] [&[i32; 4]; 4] [&[i32; 4]; 4][[i32; 4]; 4] [[i32; 4]; 4] [[i32; 4]; 4]在內容和大小方面完全不同 - 前一個數組包含四個指向其他數組的指針(4 * 4 = 16/8 * 4 =總共32個字節,具體取決於您的機器的體系結構),而后者包括順序排列的四個數組(4 * 4 * 4 =總共64個字節)。 根本沒有辦法從[[i32; 4]; 4] [[i32; 4]; 4] [[i32; 4]; 4]&[&[i32; 4]; 4] &[&[i32; 4]; 4] &[&[i32; 4]; 4]沒有重建外部數組,Rust不會為你做,因為它太多魔法了。

你真的不需要使用內部引用; 事實上,你可能甚至不需要引用在所有通過這些陣列:陣列的Copy類型Copy為好,這樣你就可以按值傳遞它們。 它們足夠小,不會對性能產生任何影響,編譯器可能會自動優化它:

fn main()  {
    // first create a couple of arrays - these will be used
    // for the vectors
    let line1: [i32; 4] = [4, 2, 3, 3];
    let line2: [i32; 4] = [3, 4, 5, 7];
    let line3: [i32; 4] = [2, 9, 6, 2];
    let line4: [i32; 4] = [5, 7, 2, 4];

    // create two holding arrays and assign
    let array_one = [line1, line3, line4, line2];
    let array_two = [line2, line1, line3, line4];

    // let's do the multiply
    let result = matrix_multiply(array_one, array_two);
    println!("{:?}", result);
}

fn matrix_multiply(vec1: [[i32; 4]; 4], vec2: [[i32; 4]; 4]) -> [[i32; 4]; 4] {
    // we need to create the arrays to put the results into
    let mut result = [[0i32; 4]; 4];

    // loop through the two vectors
    for vone in 0..4 {
        for vtwo in 0..4 {
            let mut sum = 0;
            for k in 0..4 {
                sum += vec1[vone][k] * vec2[k][vtwo];
            }
            result[vone][vtwo] = sum;
        }
   }

   result
}

在這里試試)

根據當前的社區實踐(大括號定位,間距等),我還使你的代碼更加慣用,並且我已經修復了訪問數組的奇怪語法。

如果你寫

let line1: [i32; 4] = [4, 2, 3, 3];
let line2: [i32; 4] = [3, 4, 5, 7];
let line3: [i32; 4] = [2, 9, 6, 2];
let line4: [i32; 4] = [5, 7, 2, 4];

// create two holding arrays and assign
let array_one = [line1, line3, line4, line2];

array_one的類型將是[[i32;4];4]因為行數組被復制到array_one 通過&array_one借用這個給你一些類型&[[i32;4];4] ,這與&[&[T; 4]; 4] &[&[T; 4]; 4] &[&[T; 4]; 4] (你試圖調用的功能是什么)。

選項1 - 創建[&[T; 4]; 4] [&[T; 4]; 4] [&[T; 4]; 4]

let array_one = [&line1, &line3, &line4, &line2];
some_function(&array_one);
...
fn some_function(matrix: &[&[i32;4];4]) {...}

選項2 - 更改功能坐標:

let array_one = [line1, line3, line4, line2];
some_function(&array_one);
...
fn some_function(matrix: &[[i32;4];4]) {...}

如果您對處理任意大小的多維數組感興趣,也許您會發現我的實驗性多陣列箱有用。 它基本上嘗試為兩個或多個維度提供類似於Box<[T]>&[T]&mut[T]的類型。 這是一個未經測試的例子,只是為了了解我想要做的事情:

extern crate multiarray;

use multiarray::*;

fn main() {
    // the backing memory will be a dynamically allocated
    // linear array with 4 elements in row-major (C-style) order.
    let mut matrix = Array2D::new([2, 2], 0i32);
    matrix[[0,0]] = 1; matrix[[0,1]] = 2;
    matrix[[1,0]] = 3; matrix[[1,1]] = 4;
    let mut square = Array2D::new([2, 2], 0i32);
    // the borrow methods create reference-like proxies
    mat_product(matrix.borrow(), matrix.borrow(),
                square.borrow_mut());
}

fn mat_product(a: Array2DRef<i32>, b: Array2DRef<i32>,
               mut c: Array2DRefMut<i32>) {
    let rows = a.extents()[0]; // extent of 1st dimension
    let intr = a.extents()[1]; // extent of 2nd dimension
    let cols = b.extents()[1]; // extent of 2nd dimension
    assert!(intr == b.extents()[0]);
    assert!(rows == c.extents()[0]);
    assert!(cols == c.extents()[1]);
    for i in 0..rows {
        // the i-th row of a and c...
        let a_row_i = a.eliminated_dim(0, i);
        let mut c_row_i = c.reborrow_mut().eliminated_dim(0, i);
        for j in 0..cols {
            c_row_i[j] = dot_product(a_row_i, b.eliminated_dim(1, j));
            //                                ^^^j-th column of b^^^
        }
    }
}

fn dot_product(a: Array1DRef<i32>, b: Array1DRef<i32>) -> i32 {
    a.zip(b).fold(0, |acc,(&x,&y)| acc + x * y)
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM