簡體   English   中英

在不使用java中的循環的情況下添加double []數組的元素

[英]Adding the elements of a double[] array without using a loop in java

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

我想一次得到該數組的所有元素的總和 (不使用循環)

你有任何想法嗎?

不,您無法在一個步驟中計算值列表的總和。 即使有一個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)

是的,使用循環。 這就是他們的目的。 數百個元素是陣列的小尺寸,幾乎沒有時間處理。

首先,“數百”不是“巨大的”(“數百萬”),其次,除非你有一些關於元素的先驗信息(比如它們是特定系列的一部分),否則添加元素而不進行循環是不可能的。 。

在Java 8中:

Arrays.stream(array).sum();

如果你想在多個CPU上並行:

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

我更喜歡以下方法。

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;

  }

如果您的數組已分配給cern.colt.matrix庫中的DoubleMatrix1D對象,則可以使用zSum()方法,它將返回數組中所有元素的總和,而不必循環

your_sum = your_array.zSum()

循環是最簡單,最有效的方法,例如在Java中對數組或集合的元素求和。

有一些方法可以對不涉及顯式循環的數組進行求和,但它們涉及使用模擬的高階函數,並且在用Java編寫時它們很復雜且難看。 (並且它們很昂貴並且在引擎蓋下使用循環。)

Java不是一種函數式編程語言。 如果您想/需要在Java平台上進行函數式編程,請使用Scala或Clojure。

如果你真的關心准確性,一個簡單的循環可能會導致一些問題。 雙打不包含任意精度。 這是一個簡單的例子,展示了使用循環的缺陷。

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)),更不用說所涉及對象的開銷。

因為雙精度比浮點數精確得多,所以你可能不需要使用它,除非你有大量的雙精度(數百萬/十億)和/或你的數字之間的差異很大。

編輯:如果所有數字的大小大致相同,則此代碼將有助於避免問題並保持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];
}

如果數組中的數據類型是對象類型Double ,而不是基本類型double ,那么你可以在java 8中使用stream ,如下所示:

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);

您需要在函數內部創建一個嵌套類,並在嵌套類中使用遞歸來執行添加:

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

一世

任何擁有大量雙打的人都可以查找cern.colt.list.AbstractDoubleList,它是為了優化添加(元素)等操作而構建的。

正如其他人所說,如果你想要數組中所有元素的總和,你應該寫一個循環。

循環是最簡單的方法,但是因為你要求另一個:

遞歸:

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。

朋友這是我完成的完美解決方案。我正在用字符串處理復雜的情況。 我們可以直接使用雙數組。

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;

  }

美好的一天!!!!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM