1

该程序计算2x2矩阵中负元素的平均几何平均值,我试图理解下面这个程序中的代码以及作者为什么写他写的东西,有人可以向我解释下面这段代码的作用,我觉得很难理解什么作者在代码中写了太多指针

#include <stdio.h>
#include <math.h>

#define ROWS 2
#define COLS 2
char * last_geom_err = NULL;

float geometricMean(float * arr, int rows, int cols){
    float neg_mul = 1;
    int neg_count = 0;
    float arr_elem;
    for (int i = 0; i < rows; i++)
        for (int j = 0; j < cols; j++)
            if((arr_elem = *(arr + i * cols + j)) < 0){
                neg_mul *= arr_elem;
                neg_count++;
            }
    if (neg_count == 0){
        last_geom_err = "no negative elements in array";
        return 0;
    }   
    if ((neg_count % 2 == 0) && (neg_mul < 0)){
        last_geom_err = "a negative number under the square root of even degree";
        return 0;
    }
    last_geom_err = NULL;
    return pow(neg_mul, (float)neg_count);
}

int main(){
    float arr[ROWS][COLS] = {
        1., -2.,
        -5., -6.
    };
    printf("Array:\n");
    for(int i = 0; i < 2; i++){
        for(int j = 0; j < 2; j++)
            printf("%5.2f ", arr[i][j]);
        putchar('\n');
    }
    float gm = geometricMean((float*)arr, ROWS, COLS);
    if (last_geom_err != NULL)
        printf("#Error of calculation: %s", last_geom_err);
    else
        printf("Geometric mean of negative elements of array = %5.2f", gm);
    return 0; 
}

为什么这个?

char * last_geom_err = NULL;

    float geometricMean(float * arr, int rows, int cols){
        float neg_mul = 1;
        int neg_count = 0;
        float arr_elem;
        for (int i = 0; i < rows; i++)
            for (int j = 0; j < cols; j++)
                if((arr_elem = *(arr + i * cols + j)) < 0){
                    neg_mul *= arr_elem;
                    neg_count++;
                }
        if (neg_count == 0){
            last_geom_err = "no negative elements in array";
            return 0;
        }   
        if ((neg_count % 2 == 0) && (neg_mul < 0)){
            last_geom_err = "a negative number under the square root of even degree";
            return 0;
        }
        last_geom_err = NULL;
        return pow(neg_mul, (float)neg_count);
    }

和这个

float gm = geometricMean((float*)arr, ROWS, COLS);
        if (last_geom_err != NULL)
            printf("#Error of calculation: %s", last_geom_err);
        else
            printf("Geometric mean of negative elements of array = %5.2f", gm);
        return 0
4

1 回答 1

2

程序计算 2x2 矩阵中负元素的平均几何平均值

它没有。首先,通常几何平均值仅适用于正数。可以通过说负数的几何平均值是绝对值的几何平均值的负数,以某种有意义的方式将定义扩展到负数k,但是包含负数和正数的集合的几何平均值应该是什么不清楚。扩展几何平均值的另一种有意义的方法是将其作为全纯函数扩展到其全纯域(它k > 1不会是 ℂ<sup>k 的子集)。这将包括前一个扩展作为 ℝ<sub>< 0 k上方一个分支上的值。

无论如何,几何平均值的计算将包括k某种形式的 -th 根,而给定的程序没有。现在让我们看一下代码。

float geometricMean(float * arr, int rows, int cols){
    float neg_mul = 1;
    int neg_count = 0;

初始化负数组元素的乘积及其计数。

    float arr_elem;
    for (int i = 0; i < rows; i++)
        for (int j = 0; j < cols; j++)

矩阵的内存布局为

        --------------------------------------------
arr -> | row 0 | row 1 | row 2 | ... | row (rows-1) |
        --------------------------------------------

所以row 0占用slots 0 to cols - 1row 1占用slots colsto 2*cols - 1,一般来说row k占用slots k*colsto (k+1)*cols - 1。因此arr + i*cols + j指向col jin row i

            if((arr_elem = *(arr + i * cols + j)) < 0){
                neg_mul *= arr_elem;
                neg_count++;
            }

读取矩阵元素a[i][j],如果它是负数,则将其乘以所有负数的乘积并计数。请注意,由于平坦的内存布局,人们可以简单地循环for(k = 0; k < rows*cols; ++k)和访问arr[k]这里。

    if (neg_count == 0){
        last_geom_err = "no negative elements in array";
        return 0;
    }

如果数组根本不包含负元素,则设置错误消息并返回。没有数字的(几何)平均值根本没有意义。

    if ((neg_count % 2 == 0) && (neg_mul < 0)){
        last_geom_err = "a negative number under the square root of even degree";
        return 0;
    }

如果否定条目的数量是偶数并且否定条目的乘积是负的,则设置错误消息并返回。

请注意,这是死代码。偶数个负数的乘积总是正数,浮点运算(符合 IEEE 754 或足够接近该标准;如果它完全被破坏,任何事情都可能发生)的唯一警告是下溢,乘积可能会变为 0,尽管在数学上它不是。(溢出在这里不是问题,无穷大与 0 相比,并且在乘法中表现应如此。)

    last_geom_err = NULL;
    return pow(neg_mul, (float)neg_count);
}

最后,将错误消息设置为NULL,因为没有发生异常情况并返回

(否定条目的乘积)(否定条目的数量)

对于几何平均值,最后一行应该类似于

    return pow(neg_mul, 1.0/neg_count);

但是,如果neg_mul < 0因为pow只处理整数指数的负基数,那将返回 NaN,所以

if (neg_mul < 0) {
    return -pow(-neg_mul, 1.0/neg_count);
} else {
    return pow(neg_mul, 1.0/neg_count);
}
于 2012-04-15T15:50:53.147 回答