El bucle de punto flotante ejecuta más iteraciones de lo que debería ser

Tengo este bucle que se supone que itera lx veces sobre x (rango [-1,1]) y ly veces sobre y (rango [-1,1]), 9 veces en total, ¡pero itera 16 veces! ¿¿Por qué es esto??

 #include  int main(void) { double lx=3,ly=3; double du = (1-(-1))/double(lx); double dv = (1-(-1))/double(ly); int count=0; for (double y=-1; y < 1; y += dv) for (double x=-1; x < 1; x += du) { count++; } printf("\n\n%d lss\n", count); } 

¿Seriamente?

Está iterando sobre [-1, -1/3, 1/3, 1].

Puedes ver esto poniendo una statement de salida en el bucle para ver qué está sucediendo.

Supongo que su implementación de C usa el punto flotante binario IEEE-754 de 64 bits para el double , que es la opción más común.

Todo sistema aritmético numérico es inexacto, por lo que los números con los que trabaja no son los mismos que obtendría con las matemáticas exactas.

La instrucción double du = (1-(-1))/double(lx); establece du en el valor double más cercano a 2/3, que es 0.66666666666666662965923251249478198587894439697265625.

En la primera iteración del bucle externo, y es -1. Cuando se agrega du al final de cada iteración, los resultados son:

  • -0.33333333333333337034076748750521801412105560302734375,
  • 0.3333333333333332593184650249895639717578887939453125, y
  • 0.99999999999999988897769753748434595763683319091796875.

Obviamente, el último valor de y es menor que 1, por lo que el bucle continúa para otra iteración.

Los iteradores de bucle generalmente deben usar valores enteros, de modo que sea fácil garantizar que se use la aritmética exacta. Puede escalar el iterador para producir otros valores deseados:

 for (int iy = 0; iy < 4; ++iy) { double y = iy * 2 / 3. - 1; … } 

Necesitas calcular la diferencia entre tu punto de inicio y final de una manera diferente aquí, ya que estás utilizando dobles aquí.

Así que en lugar de end - start uso end - start + 1.0 y listo.