O problema do ponto-flutuante (parte 2)

Neste post aqui falei de alguns problemas em usar ponto-flutuante. A idéia é fazê-los lembrar que ponto-flutuante tem precisão, mas não tem exatidão e os tipos inteiros têm exatidão, mas não tem precisão. Agora vou demonstrar isso para vocês com o seguinte exemplo:

/* Testando o comportaemnto de ponto-flutuante.
   Compilar com:
     gcc -O0 -o test test.c
*/
#include <stdio.h>

#define SHOW_RESULT(c) \
  printf("[%s]\n", ((c))?"yes":"no")

void testfp1(void)
{
  double x = 1.2;

  printf("x = 1.2 - 0.4 - 0.4 - 0.4; x = 0.0? ");

  x -= 0.4;
  x -= 0.4;
  x -= 0.4;

  /* Neste ponto x deveria ser 0.0, certo? ERRADO! */
  SHOW_RESULT(x == 0.0);
}

void testfp2(void)
{
  double x;
  double y;

  printf("x = (0.1 + 0.2) + 0.3; y = 0.1 + (0.2 + 0.3); x == y ? ");

  x = (0.1 + 0.2) + 0.3;
  y = 0.1 + (0.2 + 0.3);

  /* Neste ponto x deveria ser igual a y, certo? ERRADO! */
  SHOW_RESULT(x == y);
}

void testfp3(void)
{
  double x;
  double y;

  printf("x = (0.1 * 0.2) * 0.3; y = 0.1 * (0.2 * 0.3); x == y? ");

  x = (0.1 * 0.2) * 0.3;
  y = 0.1 * (0.2 * 0.3);

  /* Neste ponto x deveria ser igual a y, certo? ERRADO! */ 
  SHOW_RESULT(x == y);
}

void testfp4(void)
{
  double x;
  double y;

  printf("x = (0.1 + 0.2) * 0.3; y = (0.1 * 0.3) + (0.2 * 0.3); x == y? ");

  x = (0.1 + 0.2) * 0.3;
  y = (0.1 * 0.3) + (0.2 * 0.3);

  /* Neste ponto x deveria ser igual a y, certo? ERRADO! */
  SHOW_RESULT(x == y);
}

int main(void)
{
  testfp1();
  testfp2();
  testfp3();
  testfp4();

  return 0;
}

Ao compilar e executar o programinha veremos que todas as funções não são executadas de acordo com o que se espera:

$ gcc -O0 test test.c
$ ./test
x = 1.2 - 0.4 - 0.4 - 0.4; x = 0.0? [no]
x = (0.1 + 0.2) + 0.3; y = 0.1 + (0.2 + 0.3); x == y ? [no]
x = (0.1 * 0.2) * 0.3; y = 0.1 * (0.2 * 0.3); x == y? [no]
x = (0.1 + 0.2) * 0.3; y = (0.1 * 0.3) + (0.2 * 0.3); x == y? [no]

Então, tome cuidado com o uso de ponto-flutuante! Quem avisa amigo é!

Anúncios

Deixe um comentário

Faça o login usando um destes métodos para comentar:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s