如何使用Math.pow计算整数数组的几何平均值

3

我正在尝试使用Math.pow找到一个小整数数组的几何平均值。

这是我第一次使用这个语法,我不确定如何完成我的代码。

我正在复习去年的考试题,这是其中的一个问题。

请原谅我的代码中可能存在的错误。我仍在学习Java。

public class AverageOfArray {

public static void main(String []args){

    int [] data = new int[3];
    data[0] = 2;
    data[1] = 4;
    data[2] = 8;

    int y = 0;
    int sum = 0;
    for(int i = 0; i < data.length; i++){
        sum = sum + data[i];
        y++;
    }

    Math.pow(sum, 1.0/data.length);
    System.out.println(sum);

}

}

虽然代码没有出现错误,但它没有给我想要的输出结果。平均值应该是4。

以下是经过一些编辑后的代码:

public class AverageOfArray {

public static void main(String []args){

    int [] data = new int[3];
    data[0] = 2;
    data[1] = 4;
    data[2] = 8;


    double sum = 1.0;

    for(int i = 0; i < data.length; i++){
        sum = sum * data[i];
    }

    double geoMean = Math.pow(sum, 1.0/data.length);
    System.out.println(geoMean);

}

}

然而,现在它返回的是3.9999996? 我现在看到的是Math.abs吗?
5个回答

17

根据维基百科(https://en.wikipedia.org/wiki/Geometric_mean#Relationship_with_arithmetic_mean_of_logarithms)所述,通常实现一种不同(但等效)的几何平均数公式。该版本使用对数来避免溢出和下溢。在Java中,可以像这样表示:

class GeometricMean {
    private GeometricMean() {}

    public static void main(String[] args) {
        long[] data = new long[]{2, 4, 8};
        double gm = geometricMean(data);
        System.out.println("Geometric mean of 2, 4 and 8: " + gm );
    }

    public static double geometricMean(long[] x) {
        int n = x.length;
        double GM_log = 0.0d;
        for (int i = 0; i < n; ++i) {
            if (x[i] == 0L) {
                return 0.0d;
            }
            GM_log += Math.log(x[i]);
        }
        return Math.exp(GM_log / n);
    }
}

谢谢你的回答。我还没有学过Math.log或Math.exp!! 非常感谢!! =] - PrimalScientist

12

您的几何平均数计算结果不正确。您必须将所有值相乘,而不是相加。并且您的初始乘积必须从1.0开始。

double product = 1.0;

以后...

product = product * data[i];

此外,将 Math.pow 的结果存储在一个新变量中 -- 一个 double,因为这是 Math.pow 返回的数据类型。

double geoMean = Math.pow(product, 1.0 / data.length);

谢谢您的反馈!我正在看那个。我在另一个网站上进行了研究,他们在使用加法!!谢谢。 - PrimalScientist
是的,我现在明白了。我总是忘记捕获我的输出。谢谢! - PrimalScientist
嗯,我的输出是3.9999999999999996。我需要在这里使用Math.abs吗? - PrimalScientist
1
这里似乎出现了一些轻微的浮点数误差。对于您的目的来说,这很可能是“足够接近”的。您可以使用String.format 或者 DecimalFormat 来格式化您的数字以给定数量的小数位,例如,对于2个小数位,您可以使用4.00 - rgettman

4
public static double geoMean(double[] arr) {

    if (arr.length == 0) {
        return 0.0;
    }

    double gm = 1.0;
    for (int i = 0; i < arr.length; i++) {
        gm *= arr[i];
    }
    gm = Math.pow(gm, 1.0 / (double) arr.length);

    return gm;
}

1
你的代码存在一些问题。首先,为了得到几何平均数,你需要将值相乘。然后,仅仅调用Math.pow是无法改变值的;它会返回一个新值,你必须将其捕获。例如:
sum = Math.pow(sum, 1.0 / data.length);

啊,我明白了。谢谢。 - PrimalScientist

0
在Scala中,您可以使用对数求和(以防止溢出)来实现它,方法如下:
def geomean(values: Double*): Double =
 math.exp((values.map(math.log(_)).sum) / values.length)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接