What is a good solution for calculating an average where the sum of all values exceeds a double's limits?

前端 未结 17 2196

I have a requirement to calculate the average of a very large set of doubles (10^9 values). The sum of the values exceeds the upper bound of a double, so does anyone know a

17条回答
  •  半阙折子戏
    2020-11-29 19:01

    First of all, make yourself familiar with the internal representation of double values. Wikipedia should be a good starting point.

    Then, consider that doubles are expressed as "value plus exponent" where exponent is a power of two. The limit of the largest double value is an upper limit of the exponent, and not a limit of the value! So you may divide all large input numbers by a large enough power of two. This should be safe for all large enough numbers. You can re-multiply the result with the factor to check whether you lost precision with the multiplication.

    Here we go with an algorithm

    public static double sum(double[] numbers) { 
      double eachSum, tempSum;
      double factor = Math.pow(2.0,30); // about as large as 10^9
      for (double each: numbers) {
        double temp = each / factor;
        if (t * factor != each) {
          eachSum += each;
        else {
          tempSum += temp;
        }
      }
      return (tempSum / numbers.length) * factor + (eachSum / numbers.length);
    }
    

    and dont be worried by the additional division and multiplication. The FPU will optimize the hell out of them since they are done with a power of two (for comparison imagine adding and removing digits at the end of a decimal numbers).

     

    PS: in addition, you may want to use Kahan summation to improve the precision. Kahan summation avoids loss of precision when very large and very small numbers are summed up.

提交回复
热议问题