2012-09-05 5 views
5

He calculado los primeros 20 elementos de la serie -suma de la serie usando flotador

enter image description here

en 2 formas, 1ª - hacia delante, hacia atrás - 2do. Para esto lo hice -

#include <iostream> 
#include <math.h> 
using namespace std; 

float sumSeriesForward(int elementCount) { 
    float sum = 0; 
    for (int i = 0; i < elementCount; ++i) { 
     sum += (float) 1/(pow(3, i)); 
    } 
    return sum; 
} 

float sumSeriesBack(int elementCount) { 
    float sum = 0; 
    for (int i = (elementCount - 1); i >= 0; --i) { 
     sum += (float) 1/(pow(3, i)); 
    } 
    return sum; 
} 

int main() { 
    cout.precision(30); 
    cout << "sum 20 first elements - forward: " << sumSeriesForward(20) << endl; 
    cout << "sum 20 first elements - back: " << sumSeriesBack(20) << endl; 
} 

Y tengo -

sum 20 first elements - forward: 1.5000001192092896 
sum 20 first elements - back: 1.5 

Por favor alguien puede explicar por qué es la diferencia entre las 2 formas?

+9

Es más o menos básico [Lo que todo científico de la computación necesita saber sobre la aritmética de coma flotante] (http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) material. –

+6

Al sumar una serie de números usando coma flotante, siempre suma los números más pequeños primero - Punto flotante básico 101 - lo aprendí hace 40 años. –

+0

@HotLicks: ¿te refieres a que proporciona una mayor precisión? – URL87

Respuesta

10

En general, los números de coma flotante no pueden representar valores exactamente. Cuando opera en los valores, los errores se propagan. En su ejemplo, al computar al revés, agrega valores pequeños a números cada vez mayores, teniendo una buena probabilidad de que la suma de los números pequeños hasta ahora tenga un efecto en el número mayor. Por otro lado, cuando calcula hacia adelante, comienza con los números grandes y los números más pequeños tienen un efecto cada vez menor en él. Es decir, cuando sumas siempre quieres sumar lo más pequeño a lo más grande.

Solo considere mantener una suma en un número fijo de dígitos. Por ejemplo, mantener 4 dígitos y sumar estos números de arriba a abajo y de abajo a arriba:

values top to bottom bottom to top 
10.00  10.00   10.01 
0.004  10.00   0.010 
0.003  10.00   0.006 
0.002  10.00   0.003 
0.001  10.00   0.001 

números de punto flotante trabajan de la misma manera, utilizando un número fijo de dígitos binarios [].

+0

Ejemplo muy útil, gracias. – URL87

+0

Aunque ir de abajo hacia arriba abre la posibilidad de reemplazar las repetidas llamadas 'pow()' a 'tmp * = 3;'. Todavía podría funcionar de otra manera, pero tendrías que sembrar tmp usando un pow inicial() y luego dividir cada vez. – Ghost2

5

Para mejorar la precisión al sumar números, considere el Kahan summation algorithm. Esto reduce significativamente el error en comparación con el enfoque obvio (incluidos los números de suma de menor a mayor).