FORTRAN 77 等效于 C# 的三维数组初始化



我正在尝试将FORTRAN 77中声明和初始化的三维数组编码为C#中的等效数组。

经过一些研究,我发现FORTRAN 77遵循列主要方法。我仍然无法想象如何表示在 C# 中的 FORTRAN 77 中初始化的三维数组。下面是声明和初始化三维数组的 FORTRAN 77 代码:

real*4 temperature_factors(2,6,9)/
c  .000,.054, .055,.070, .071,.085, .086,.105, .106,.200,
c  -1.0,-1.0,
c  -1.0,-1.0, -1.0,-1.0, .125,.164, .165,.204, .205,.404,
c  .405,.604,
c  0.0,12.0, 12.1,35.4, 35.5,55.4, 55.5,150.4, 150.5,250.4,
c  250.5,500.4,
c  0.0,54.0, 55.0,154.0, 155.0,254.0, 255.0,354.0, 355.0,424.0,
c  425.0,604.0,
c  0.0,4.4, 4.5,9.4, 9.5,12.4, 12.5,15.4, 15.5,30.4,
c  30.5,50.4,
c  .000,.035, .036,.75, .76,.185, -1.,  -1.,  -1., -1.,
c   -1., -1.,
c   -1., -1.,  -1., -1., -1., -1.,.186,.304, .305,.604,
c  .605,1.004,
c  -1.0,10.0, -1.0,-1.0, -1.0,-1.0, -1.0,-1.0, -1.,-1.0,
c  -1.0,10.0,
c  .000,.053, .054,.100, .101,.360, .361,.649, .650,1.249,
c  1.250,2.049/

我最初尝试用 C# 表示上述内容:

double[, ,] temperature_factors = new double[2, 6, 9]
{
{
{0.000, 0.054,  0.055,  0.070,  0.071,  0.085,  0.086,  0.105,  0.106,},
{0.200, -1.0,   -1.0,   -1.0,   -1.0,   -1.0,   -1.0,   0.125,  0.164},
{0.165, 0.204,  0.205,  0.404,  0.405,  0.604,  0.0,    12.0,   12.1},
{35.4,  35.5,   55.4,   55.5,   150.4,  150.5,  250.4,  250.5,  500.4},
{0.0,   54.0,   55.0,   154.0,  155.0,  254.0,  255.0,  354.0,  355.0},
{424.0, 425.0,  604.0,  0.0,    4.4,    4.5,    9.4,    9.5,    12.4}
},
{
{12.5,  15.4,   15.5,   30.4,   30.5,   50.4,   0.000,  0.035,  0.036},
{0.75,  0.76,   0.185,  -1.0,   -1.0,   -1.0,   -1.0,   -1.0,   -1.0},
{-1.0,  -1.0,   -1.0,   -1.0,   -1.0,   -1.0,   0.186,  0.304,  0.305},
{0.604, 0.605,  1.004,  -1.0,   10.0,   -1.0,   -1.0,   -1.0,   -1.0},
{-1.0,  -1.0,   -1.0,   -1.0,   -1.0,   10.0,   0.000,  0.053,  0.054},
{0.100, 0.101,  0.360,  0.361,  0.649,  0.650,  1.249,  1.250,  2.049}
}
};

但显然这是不正确的。任何人都可以帮我初始化用 FORTRAN 77 编写的三维数组,使其在 C# 中等效。

谢谢。

Fortran 数组是列主数组,因此 Fortran 代码中的文字值按A(1,1,1), A(2,1,1), A(1,2,1), A(2,2,1), ..., A(1,6,9), A(2,6,9)顺序填充为A(其中A表示temperature_factors(。另一方面,C# 数组是行主要的(根据此页面和一个小型测试(请参阅此答案的底部((,因此我认为我们需要切换索引的顺序以直接使用文字值的序列。具体来说,我们首先从文字值创建一个 1D(临时(数组,如

double[] arr1 = new double[ 9 * 6 * 2 ]
{
.000,.054,  .055,.070,  .071,.085,   .086,.105,   .106,.200,    -1.0,-1.0,
-1.0,-1.0,  -1.0,-1.0,  .125,.164,   .165,.204,   .205,.404,    .405,.604,
0.0,12.0,   12.1,35.4,  35.5,55.4,   55.5,150.4,  150.5,250.4,  250.5,500.4,
0.0,54.0,   55.0,154.0, 155.0,254.0, 255.0,354.0, 355.0,424.0,  425.0,604.0,
0.0,4.4,    4.5,9.4,    9.5,12.4,    12.5,15.4,   15.5,30.4,    30.5,50.4,
.000,.035,  .036,.75,   .76,.185,    -1.0,-1.0,   -1.0,-1.0,    -1.0,-1.0,
-1.0,-1.0,  -1.0,-1.0,  -1.0,-1.0,   .186,.304,   .305,.604,    .605,1.004,
-1.0,10.0,  -1.0,-1.0,  -1.0,-1.0,   -1.0,-1.0,   -1.0,-1.0,    -1.0,10.0,
.000,.053,  .054,.100,  .101,.360,   .361,.649,   .650,1.249,    1.250,2.049
};

然后通过循环逐个复制元素(最右侧的索引k应该运行最快(:

double [,,] arr3 = new double[ 9, 6, 2 ];
int ind = 0;
for (int i = 0; i < 9; i++)
for (int j = 0; j < 6; j++)
for (int k = 0; k < 2; k++) {
arr3[ i, j, k ] = arr1[ ind ];
ind++;
}

或者等效地,直接复制一块内存(根据此页面(

Buffer.BlockCopy( arr1, 0, arr3, 0, arr1.Length * sizeof(double) );

我们可以通过打印一些arr3元素来检查结果:

// using static System.Console;
WriteLine( arr3[ 0, 0, 0 ] );
WriteLine( arr3[ 0, 0, 1 ] );
WriteLine( arr3[ 0, 1, 0 ] );
WriteLine( arr3[ 0, 1, 1 ] );
WriteLine( "..." );
WriteLine( arr3[ 8, 4, 0 ] );
WriteLine( arr3[ 8, 4, 1 ] );
WriteLine( arr3[ 8, 5, 0 ] );
WriteLine( arr3[ 8, 5, 1 ] );

这给了

0         // A(1,1,1) in Fortran
0.054     // A(2,1,1)
0.055     // A(1,2,1)
0.07      // A(2,2,1)
...
0.65      // A(1,5,9)
1.249     // A(2,5,9)
1.25      // A(1,6,9)
2.049     // A(2,6,9)

要使用与 Fortran 相同的索引顺序,它也可能有助于 创建另一个索引顺序颠倒的 3D 数组,以便:

double [,,] arr3_alt = new double[ 2, 6, 9 ];
for (int i = 0; i < 2; i++)
for (int j = 0; j < 6; j++)
for (int k = 0; k < 9; k++) {
arr3_alt[ i, j, k ] = arr3[ k, j, i ];
}
WriteLine( arr3_alt[ 0, 0, 0 ] );
WriteLine( arr3_alt[ 1, 0, 0 ] );
WriteLine( arr3_alt[ 0, 1, 0 ] );
WriteLine( arr3_alt[ 1, 1, 0 ] );
WriteLine( "..." );
WriteLine( arr3_alt[ 0, 4, 8 ] );
WriteLine( arr3_alt[ 1, 4, 8 ] );
WriteLine( arr3_alt[ 0, 5, 8 ] );
WriteLine( arr3_alt[ 1, 5, 8 ] );

这是一个迷你测试,我试图检查对齐方式 内存中的数组元素:

int[,] A = new int[2,3] { {1,2,3}, {4,5,6} };
int[]  B = new int[6];
Buffer.BlockCopy( A, 0, B, 0, sizeof(int) * 6 );  // A=src, B=dest, 0=offset, count=in-bytes
WriteLine( "B[0] = " + B[0] + " A[0,0] = " + A[0,0] );
WriteLine( "B[1] = " + B[1] + " A[0,1] = " + A[0,1] );
WriteLine( "B[2] = " + B[2] + " A[0,2] = " + A[0,2] );
WriteLine( "B[3] = " + B[3] + " A[1,0] = " + A[1,0] );
WriteLine( "B[4] = " + B[4] + " A[1,1] = " + A[1,1] );
WriteLine( "B[5] = " + B[5] + " A[1,2] = " + A[1,2] );

这给了

B[0] = 1 A[0,0] = 1
B[1] = 2 A[0,1] = 2
B[2] = 3 A[0,2] = 3
B[3] = 4 A[1,0] = 4
B[4] = 5 A[1,1] = 5
B[5] = 6 A[1,2] = 6

最新更新