Jump to content
JSA

Erro ao comparar números float na condição do if

Recommended Posts

Olá a todos.

Observem o seguinte código extremamente simples:

 

#include <stdio.h>

 

int main()

{

float n1 = 9.8;

 

if (n1 == 9.8)

{

printf("ok!\n\n");

}

 

printf("Fim do programa...!\n");

scanf("%*c");

return 0;

}

 

Esse código não gera a frase ok! porque o compilador não enxerga n1 igual 9.8 apesar de, visualmente, a condição ser verdadeira devido a comparação entre números reais idênticos.

Porém, quando eu insiro cast antes do 9.8 na condição do if o código funciona corretamente: if (n1 == (float) 9.8)

Esse problema só existe quando eu uso números reais do tipo float diferentes de 9.0 e 9.5, ou seja, escrevendo dessa forma if (n1 == 9.0) ou desta outra forma if (n1 == 9.5), sem cast, o código funciona perfeitamente.

Para números dos tipos int e double esse problema de comparação na condição do if não ocorre.

Estou usando o codeblocks, com compilador GCC, no windows 7, processador i3, 64bits.

 

Alguém com mais anos de prática na Linguagem C poderia esclarecer por qual razão o tipo floatnecessita de casting na condição do if?

Share this post


Link to post
Share on other sites
#include <stdio.h>


int main()

{

float n1 = 9.8;


if ( n1 == 9.8f) //Colocando "f" desta forma você declara ao if que sua variável é um float, caso contrário o if reconhece o seu "9.8" como double.

{

printf("ok!\n\n");

}


printf("Fim do programa...!\n");

scanf("%*c");

return 0;

}

Share this post


Link to post
Share on other sites
Então @x8mhz , agradeço por participar do tópico.
Realmente a solução é está. Eu já tinha enxergado isto ao usar o cast antes do número (float) 9.8.
E sim, a especificação de tipo do literal numérico (inserir o f após o numero real) também é uma forma de definir um tipo para o número. Legal que você tenha visto isso também.
A minha maior curiosidade era saber PORQUE só o tipo float necessita de casting (ou definição literal do tipo do dado) dentro do if .
Depois de passar algum tempo estudando, focado em encontrar uma justificativa eis que a solução foi observada.
O if nesta situação, não tem nada a ver com essa questão do float, a não ser possibilitar a sintaxe para a comparação.

O problema está na declaração de constantes dentro do programa. Isso mesmo, constantes.

Sempre que colocamos um número PONTO FLUTUANTE dentro do código que NÃO tenha sido atrelado a um tipo, o COMPILADOR passa a tratar este número (por padrão) como sendo uma constante do tipo DOUBLE!
Por isso que a condição do if é falsa sempre que estiver desta forma:

 float n1 = 9.8;
 
 if ( n1 == 9.8 )
 {
      //instruções
 }

A variável n1, por declaração, é do tipo float e a constante 9.8 está sendo visto pelo compilador como sendo uma constante double. Para o compilador, um número ponto flutuante com precisão estabelecida pelo tipo float é diferente de um número ponto flutuante com precisão estabelecida pelo tipo double. Ambos possuem precisões distintas.
Ao colocar o cast ou a especificação literal de tipo, ambos os números 9.8 passam a possuir a mesma precisão, imposta pelo tipo float. Consequentemente, a condição do if após a alteração passa a ser verdadeira. :D






Share this post


Link to post
Share on other sites

 


Para o compilador, um número real float é diferente de um número real do tipo double.
Ao colocar o cast ou a definição literal de tipo igualamos os tipos numéricos e a condição do if passa a ser verdadeira pois ambos os números serão do tipo float e possuem o valor 9.8.



Não é bem assim.
Por padrão, constantes numéricas de ponto flutuante são double.Veja: por padrão -> isso está no ISO C.
Mas o que acontece no if é que a representação de 9.8 possui precisão menor no float que no double.

Share this post


Link to post
Share on other sites

Não é bem assim.

Por padrão, constantes numéricas de ponto flutuante são double.Veja: por padrão -> isso está no ISO C.

Mas o que acontece no if é que a representação de 9.8 possui precisão menor no float que no double.

 

_Isis_ o que você disse é exatamente o que eu falei no poste anterior. Não vejo diferença!

 

Quando eu falo por padrão, estou querendo dizer, levando em consideração as regras oficiais da linguagem, como é o caso das documentadas na ISO C.

 

Como eu falei, por padrão, literais não tipados são considerados constantes para o compilador, por exemplo, o 9.8 que se encontra na condição if.

Quando um literal não tipado é um número ponto flutuante, por padrão o compilador (certamente baseando-se em regras documentadas no ISO C) encara a constante como double.

 

Se o compilador trata 9.8 como double e inicialmente a comparação foi em relação a um 9.8 float (da variável n1), sem dúvida a comparação estava dando falso porque existia uma comparação entre números de tipos distintos, logo com precisões distintas. :)

 

 

Share this post


Link to post
Share on other sites

 

 

Para o compilador, um número ponto flutuante float é diferente de um número ponto flutuante do tipo double.

(...)
Ao colocar o cast ou a especificação literal de tipo igualamos os tipos numéricos (...)

Isso pra mim quer dizer que você está comparando apenas o tipo da variável, não o conteúdo da mesma.

Share this post


Link to post
Share on other sites

Isso pra mim quer dizer que você está comparando apenas o tipo da variável, não o conteúdo da mesma.

Foi questão de semântica.

Não existe comparação direta entre um tipo e outro na linguagem C, por exemplo, if (float == double).

Certamente comparamos o conteúdo que é moldado pelo o tipo da variável que armazena tal conteúdo.

 

Porém, sua observação foi interessante.

Escrevi de outra forma o texto para enfatizar mais ainda a questão da comparação entre os conteúdos numéricos envolvidos e suas respectivas precisões.

 

 

Share this post


Link to post
Share on other sites

O C11 passa a permitir esse tipo de coisa:
http://stackoverflow.com/questions/6280055/how-do-i-check-if-a-variable-is-of-a-certain-type-compare-two-types-in-c

A utilidade disso é que fica no ar (ex: programadores Python dizem que se vc está verificando tipo de alguma coisa, então está fazendo tudo errado)

Fora da mão do programador, internamente, há a comparação dos tipos de variáveis p/ fazer as conversões aritméticas e lembro vagamente das "restrições" do if (numa das seções do padrão ISO) listar que os dois operandos devem ser numéricos (entre outras coisas). Mas isso já serve p/ implementação de compiladores.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Similar Content

    • By giovannaalves
      Apareceu esse erro na página para retornar os dados do tabela do banco de dados:
      Fatal error: Call to a member function query() on a non-object in /home/storage/e/e6/47/grupoct/public_html/rondact/ronda2.php on line 4
       
      Meu código:
      <?php
          include("conexao.php");
          $consulta = "SELECT * FROM TAG_LIDA";
          $con = $mysqli->query($consulta) or die($mysqli->error);
          
      ?>
      <html>
          <head>
              <meta charset="utf-8">
          </head>
          <body>
              <table border="1">
                  <tr>
                      <td>Código posto</td>
                      <td>Data</td>
                      <td>Hora</td>
                      <td>Nome posto</td>
                      <td>Tag</td>
                  </tr>
                  <?php while($dado = $con->mysql_fetch_array()){ ?>
                  <tr>
                      <td><?php echo $dado["TAG_COD_POSTO"]; ?></td>
                      <td><?php echo date("d/m/Y", strtotime( $dado["TAG_DATA"])); ?></td>
                      <td><?php echo $dado["TAG_HORA"]; ?></td>
                      <td><?php echo $dado["TAG_NOME_POSTO"]; ?></td>
                      <td><?php echo $dado["TAG_TAG"]; ?></td>
                  </tr>
                  <?php } ?>
              
              </table>
          </body>
      </html>
    • By giovannaalves
      Apareceu esse erro na página para retornar os dados do tabela do banco de dados:
      Fatal error: Call to a member function query() on a non-object in /home/storage/e/e6/47/grupoct/public_html/rondact/ronda2.php on line 4
       
      Meu código:
      <?php
          include("conexao.php");
          $consulta = "SELECT * FROM TAG_LIDA";
          $con = $mysqli->query($consulta) or die($mysqli->error);
          
      ?>
      <html>
          <head>
              <meta charset="utf-8">
          </head>
          <body>
              <table border="1">
                  <tr>
                      <td>Código posto</td>
                      <td>Data</td>
                      <td>Hora</td>
                      <td>Nome posto</td>
                      <td>Tag</td>
                  </tr>
                  <?php while($dado = $con->mysql_fetch_array()){ ?>
                  <tr>
                      <td><?php echo $dado["TAG_COD_POSTO"]; ?></td>
                      <td><?php echo date("d/m/Y", strtotime( $dado["TAG_DATA"])); ?></td>
                      <td><?php echo $dado["TAG_HORA"]; ?></td>
                      <td><?php echo $dado["TAG_NOME_POSTO"]; ?></td>
                      <td><?php echo $dado["TAG_TAG"]; ?></td>
                  </tr>
                  <?php } ?>
              
              </table>
          </body>
      </html>
    • By RodrigoCesar
      Boa noite,
      estou tendo a seguinte questão,  estou precisando posicionar elementos (divs) um do lado do outro de forma que fiquem responsivos então os mesmos desçam em fiquem um em baixo do outro em telas menores. Ou seja, quando em tela grande de pc um do lado do outro, em telas menores móveis um em cima do outro. O recomendado pra isso seria usar float, porém preciso que ao ficar um em cima do outro os elementos fiquem centralizados na tela e a propriedade float sempre joga os elementos pra direita ou pra esquerda, não deixa ficar centralizado. Preciso então posicionar um do lado do outro sem uso de float ou encontrar outra solução, segue código abaixo. Desde já agradeço.
       
      <!DOCTYPE html> <html lang="pt-br"> <head> <meta charset="utf-8"> <title></title> <link rel="stylesheet" type="text/css" href="estilo.css" /> </head> <body> <div class="blocos_caracteres"> <div class="blocos_caracteres_content_1"> <p>oi</p> </div> <div class="blocos_caracteres_content_2"> <p>oi</p> </div> <div class="blocos_caracteres_content_3"> <p>oi</p> </div> <div class="blocos_caracteres_content_4"> <p>oi</p> </div> </div> </body> </html> /****reset****/ html { margin:0; padding:0; border:0; height:100%; } body { margin:0; padding:0; border:0; height:100%; } ul, ol, li {list-style:none;} /****reset****/ .blocos_caracteres {width:94%; margin: 0 auto; } .blocos_caracteres_content_1 {width:25%; height:300px; min-width: 250px; background-color: yellow; float: left; } .blocos_caracteres_content_2 {width:25% ; height:300px; min-width: 250px; background-color: green; float: left; } .blocos_caracteres_content_3 {width:25% ; height:300px; min-width: 250px; background-color: blue; float: left;} .blocos_caracteres_content_4 {width:25% ; height:300px; min-width: 250px; background-color: red; float: left;}  
    • By VitinhoBBK
      Seguinte, estou tentando criar um jogo da velha mas e está causando um erro ao compilar, aparece um erro dizendo->|error: cannot convert 'char (*)[3]' to 'char*' for argument '1' to 'bool verificaX(char*)', alguem sabe como posso resolver ???! (Aparentemente não ta dando pra armazenar o endereço do vetor casas dentro do ponteiro das funções...

      Obs: Aceito sugestões para melhorar meu código, grato.(Ignorem as bibliotecas inúteis)
       
       
      #include <iostream> #include <stdio.h> //Para função gets #include <stdlib.h> //Para função malloc #include <math.h> #include <iomanip> //JOGO DA VELHA using namespace std; int jogadas=0; bool verificaX(char *vetor); bool verificaO(char *vetor); int main(){ char casas[3][3]={' ',' ',' ',' ',' ',' ',' ',' ',' '}; int l=0,c=0; while(jogadas<9){ cout << "\t\t" << casas[0][0] << " | " << casas[0][1] << " | " << casas[0][2] << "\n"; cout << "\t\t_________\n"; cout << "\t\t" << casas[1][0] << " | " << casas[1][1] << " | " << casas[1][2] << "\n"; cout << "\t\t_________\n"; cout << "\t\t" << casas[2][0] << " | " << casas[2][1] << " | " << casas[2][2] << "\n\n\n"; cout << "Digite uma linha: "; cin >> l; cout << "Digite uma coluna: "; cin >> c; while(l<=0 || c <=0 || l>3 || c>3){ system("cls"); cout << "Linha ou Coluna não existe!"; cout << "Digite uma linha: "; cin >> l; cout << "Digite uma coluna: "; cin >> c; } system("cls"); if(jogadas%2==0){ casas[--l][--c]='X'; }else{ casas[--l][--c]='O'; } jogadas++; verificaX(casas); verificaO(casas); } if(verificaX){ cout << "Jogador X ganhou!"; }else if(verificaO){ cout << "Jogador O ganhou!"; }else{ cout << "Empate!"; } return(0); } bool verificaX(char *vetor){ int l,c; for(l=0;l<3;l++){ if(vetor[l][0] && vetor[l][1] && vetor[l][2] == 'X'){ jogadas=10; return true; }else if(vetor[0][c] && vetor[1][c] && vetor[2][c] == 'X'){ jogadas=10; return true; } c++; } return 0; } bool verificaO(char *vetor){ int l,c; for(l=0;l<3;l++){ if(*vetor[l][0]=='X' && *vetor[l][1]=='X' && *vetor[l][2] == 'X'){ jogadas=10; return o=true; }else if(*vetor[0][c]=='X' && *vetor[1][c]=='X' && *vetor[2][c] == 'X'){ jogadas=10; return o=true; } c++; } return 0; }
    • By 11closed
      Olá, boa tarde! 
      Estou com uma duvida, que pelo o que pesquisei, é bastante discutida nas comunidades de programadores e cada um fala uma coisa, por tanto vim até aqui para tentar chegar a uma conclusão.
       
      Gostaria de gravar valores financeiros no BD de alguma forma que não traga problemas futuros, por causa de possiveis arredondamentos automaticos.
      Quero saber qual o melhor mecanismo para gravar no campo de valores financeiros, valores com decimais e dizimas, exe: 0.2308, 128.997, 1.28989 ..etc independentemente da quantidade de numeros no dizimas, eu preciso saber a quantidade exata.
       
      Obrigado, no aguardo
       
×

Important Information

Ao usar o fórum, você concorda com nossos Terms of Use.