【问题标题】:FORTRAN 77 3 dimensional array initialization equivalent to C#FORTRAN 77 3 维数组初始化等效于 C#
【发布时间】:2017-08-19 16:26:07
【问题描述】:

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

在做了一些研究后,我发现 FORTRAN 77 遵循列主要方法。我仍然无法想象如何在 C# 中表示在 FORTRAN 77 中初始化的 3 维数组。这是声明和初始化 3 维数组的 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 编写的 3 维数组初始化为 C# 中的等价物。

谢谢。

【问题讨论】:

    标签: c# fortran fortran77


    【解决方案1】:

    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# 数组是行优先的(根据这个page 和一个迷你测试(请参阅这个答案的底部)),所以我认为我们需要切换索引的顺序以使用序列直接的文字值。具体来说,我们首先从字面值创建一个一维(临时)数组

    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++;
    }
    

    或者等效地,直接复制一块内存(根据这个page

    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
    

    【讨论】:

    • 更直接的方式可能是double[,,] arr3 = new double[ 9, 6, 2 ] { { {.000,.054}, {.055,.070}, ... {1.250,2.049} }};,但是添加很多{}可能比较繁琐??
    • 嗯,不确定我是否同意这个答案。 Fortran 数组是 2*6*9,但 C# 数组是 9*6*2。当然也应该是2*6*9 ?
    • 我也不是 100% 确定,但从一些测试看来,A[2, 2](在 C# 中)的元素在内存中对齐,使得 A[0,0] - > A[0,1] -> A[1,0] -> A[1,1] (在我的 Mac + homebrew + mono 上)。所以我假设 C# 中的矩形数组是连续的,但是嗯,请纠正它...(如果完全错误,我将删除答案。)
    • 当然,我想我们也可以声明 A[2,6,9] 并使用转置复制元素(以便 C# 和 Fortran 之间的索引顺序相同)。
    猜你喜欢
    • 2012-05-20
    • 2011-02-15
    • 2013-03-02
    • 2012-09-27
    • 2011-04-12
    • 1970-01-01
    相关资源
    最近更新 更多