在不使用java中的循环的情况下添加double []数组的元素

时间:2010-11-04 07:29:48

标签: java

我有一个巨大的 double [] 。 (例如:double[] array = new double[] {2.0, 3.1, 4.2, 8.9, 10.11, ........}

我希望一次获得该数组的所有元素的总和。 (不使用循环)

你有任何想法吗?

13 个答案:

答案 0 :(得分:10)

不,您无法在一个步骤中计算值列表的总和。即使有一个API方法或某个提供sum函数的库,它也会在内部使用循环。求和算法的复杂性为O(n)(对于单CPU)。

出路可能是使用并行计算,但这是回答你的问题的理论方法。您至少需要与阵列单元一样多的CPU来计算步骤中的总和。 (或者一个虚构的CPU,其FP寄存器数量与数组值一样多)。


在开始查看Java或其他库的API之前:

 public static double sum(double...values) {
   double result = 0;
   for (double value:values)
     result += value;
   return result;
 }

用法:

 double sum = sum(array);  // this is in your main code -> no loop (visible)

答案 1 :(得分:9)

是的,使用循环。这就是他们的目的。数百个元素对于数组来说是一个小巧的大小,几乎没有时间处理。

答案 2 :(得分:4)

首先,“数百”不是“巨大的”(“数百万”),其次,除非你有一些关于元素的先验信息(如果它们是一部分的话),那么添加元素而不进行循环是不可能的。特别系列)。

答案 3 :(得分:4)

在Java 8中:

Arrays.stream(array).sum();

如果你想在多个CPU上并行:

Arrays.stream(array).parallel().sum();

答案 4 :(得分:3)

我更喜欢以下方法。

package rfcampusdata;

public class TestClass {
  public static void main(String[] args) {
    String str = "1,2,3,4,5";
    String[] arr = str.split(",");
    int length = arr.length;

    System.out.println(sum(length, arr));
  }

  static Double temp = new Double(0);

  public static Double sum(int length, String[] arr) {
    int length_m = length - 1;
    String[] arr_m = arr;
    temp += Double.parseDouble(arr[length_m]);
    if (length_m != 0) {
      sum(length_m, arr_m);
    } else {
      // temp += Integer.parseInt(arr[0]);
      // System.out.println(temp);
    }
    return temp;

  }

答案 5 :(得分:2)

循环是最简单,最有效的方法,例如在Java中对数组或集合的元素求和。

有些方法可以对不涉及显式循环的数组进行求和,但它们涉及使用模拟高阶函数,并且在用Java编写时它们很复杂且难看。 (而且它们很昂贵并且在引擎盖下使用循环。)

Java不是一种函数式编程语言。如果您希望/需要在Java平台上进行函数式编程,请使用Scala或Clojure。

答案 6 :(得分:2)

如果你真的关心准确性,一个简单的循环可能会导致一些问题。双打不包含任意精度。这是一个简单的例子,展示了使用循环的缺陷。

float f = 0;
for(int i = 0; i < 1000*1000*1000; ++i){
    ++f;
}
System.out.println(f);

我们希望f为10亿,或1.0E9,但我们得到1.6777216E7。这是因为浮点数只能保持大约6-7位数的精度。双精度可以保持大约16-17位数的精度,这意味着它不太可能出现问题,但它无法解决问题。

要解决这个问题,我们不需要在它们之间存在很大的差异时添加两个数字。这可以使用PriorityQueue完成。我们将取出前两个数字,添加它们,然后将它们放回队列中。当队列只剩下1个号码时,我们将其返回。

public static double queueSum(double[] da){
    PriorityQueue<Double> pq = new PriorityQueue<Double>(da.length);
    for(double d : da)
        pq.add(d);
    while(pq.size() > 1)
        pq.add(pq.poll() + pq.poll());
    return pq.poll();
}

当然,准确性确实是以时间为代价的。这从循环和的O(n)变为O(n lg(n)),更不用说所涉及对象的开销。

因为双精度比浮点数精确得多,所以你可能不需要使用它,除非你有大量的双精度数(数百万/十亿)和/或你的数字之间的数量差别很大。 / p>

编辑: 如果所有数字的大小大致相同,则此代码将有助于避免问题并保持O(n)时间。如果两个样本之间存在较大的幅度差异,或者数字以可能导致较大幅度差异的方式分布,则可能会遇到与以前相同的问题。

public static double treeSum(double[] da){
    double[] dc = da.clone();
    int len = dc.length;
    while(len > 1){
        len = (len + 1) / 2;
        for(int i = 0; i < len; ++i)
            dc[i] += dc[i + len];
        dc[len] = 0;
    }
    return dc[0];
}

答案 7 :(得分:2)

如果您的数组已分配给cern.colt.matrix库中的DoubleMatrix1D对象,则可以使用zSum()方法,它将返回数组中所有元素的总和而无需循环

your_sum = your_array.zSum()

答案 8 :(得分:2)

如果数组中的数据类型是对象类型 Double ,而不是基本类型 double ,那么您可以在<中使用 strong> java 8 像这样:

Double[] test = new Double[] {2.0, 3.1, 4.2, 8.9, 10.11};
List<Double> list = Arrays.asList(test);
double sum = list.stream().mapToDouble(p -> p).sum();
System.out.println(sum);

答案 9 :(得分:1)

任何拥有大量双打的人都可以查找cern.colt.list.AbstractDoubleList,它是为了优化添加(元素)等操作而构建的。

正如其他人所说,如果你想要数组中所有元素的总和,你应该写一个循环。

答案 10 :(得分:1)

循环是最简单的方法,但是因为你要求另一个:

递归:

double sumResult = sum(data, 0, 0);

double sum(double [] d, int sum, int index) {
  if ( index > d.length ) return sum;
  else return sum(d, sum + d[index], index+1);
}

我没有测试过,但它应该在上面的某处工作。

编辑:不建议使用这样的构造,因为对于大型数组,您可能会非常快地命中StackOverflowException。

答案 11 :(得分:1)

你需要在函数内部创建一个嵌套类,并在嵌套类中使用递归来进行添加:

public double sumArrayNoLoop(double[] v){
 class compute {
            double  total = 0.0;
            public void sumArray(double[] v,int offset){
                if((offset - 1) < 0) return;
                if(offset > (v.length - 1)) offset = v.length;
                total += v[offset - 1];
                sumArray(v,offset - 1);

            }

        }

    compute c = new compute();
    c.sumArray(v, v.length);
    return c.total;
}

答案 12 :(得分:1)

朋友这是我完成的完美解决方案。我正在用字符串处理复杂的情况。我们可以直接使用双数组。

public class TestClass {
  public static void main(String[] args) {
    String str = "1,2,3,4,5";
    String[] arr = str.split(",");
    int length = arr.length;

    System.out.println(sum(length, arr));
  }

  static Double temp = new Double(0);

  public static Double sum(int length, String[] arr) {
    int length_m = length - 1;
    String[] arr_m = arr;
    temp += Double.parseDouble(arr[length_m]);
    if (length_m != 0) {
      sum(length_m, arr_m);
    } else {
      // temp += Integer.parseInt(arr[0]);
      // System.out.println(temp);
    }
    return temp;

  }

美好的一天!!!!