jueves, julio 12, 2007

División por cero

Ayer se me ocurrió meterme en la sección de Fórmula 1 de la página www.telecinco.es para ver las estadísticas de la siguiente carrera, que se celebrará en Alemania, y me encontré con esto:




¿Ven algo raro? Espero que si...

Partiendo de que todos podemos cometer un fallo así(si no lo admites, caerás antes en un error parecido o peor), he intentado reconstruir el método que usa para realizar esta curiosa estadística:


#define NPILOTOS 4

int NumVotaciones; /* número de votaciones totales */
int VotacionesPorPiloto[NPILOTOS]; /* las votaciones dadas a cada piloto */
float Resultados[NPILOTOS]; /* los resultados que se mostrarán */

for (int i=0; i < NPILOTOS; i++){
Resultados[i]=(VotacionesPorPiloto[i] / (float)NumVotaciones )*100; /* Línea 73 */
}


Podría ser esto, por ejemplo. Se intenta dividir cuatro veces por 0, por lo que parece obvio que está dentro de un bucle y el error esta dentro(de ahí los warnings mostrados en la imagen en la línea 73). A pesar de las pocas líneas, se puede caer en dos errores típicos:

- La división por 0.
- La división real.

El primer error podría tener dos soluciones:

- Usar un if si no se quiere usar control de excepciones,preguntando si el número de votaciones totales es 0. Si es 0, te ahorras los cálculos y el resultado es 0 siempre.

- Hacer una votación para evitar el 0 o inicializar NumVotaciones a 1. Aunque siendo PHP, el valor de la variable podría venir de una base de datos o de un archivo, y para evitar hacer inicializaciones directas, se podría probar con algo asi:

Resultados[i]=(VotacionesPorPiloto[i] / (float)(NumVotaciones+1) )*100; /*

Sumando un 1 al denominador nos evitamos el problema, pero esta solución sólo es útil si sabemos que el número de votaciones es grande(sumarle una unidad sería despreciable). En otro caso, afectaría a los resultados.

El segundo error podría tener dos soluciones:

- Convertir la variable NumVotaciones a float.
- Hacer el cast para forzar la división real, tal y como lo he puesto.

Aunque son errores básicos, lo vemos con demasiada frecuencia. Por lo que se ve ni siquiera se molestó en probar el código(puede que sea un código ya generado y sólo use la función), porque el código revienta en la primera ejecución.

Supongo que si se votara por primera vez, se arreglaría el problema. Yo no lo he hecho aún, así que puedes intentarlo.

No hay comentarios: