Ir para conteúdo
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?

Compartilhar este post


Link para o post
Compartilhar em outros 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;

}

Compartilhar este post


Link para o post
Compartilhar em outros 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






Compartilhar este post


Link para o post
Compartilhar em outros 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.

Compartilhar este post


Link para o post
Compartilhar em outros 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. :)

 

 

Compartilhar este post


Link para o post
Compartilhar em outros 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.

Compartilhar este post


Link para o post
Compartilhar em outros 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.

 

 

Compartilhar este post


Link para o post
Compartilhar em outros 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.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar Agora

  • Conteúdo Similar

    • Por wolf_black
      preciso Escrever um algoritmo que leia três notas, calcule e imprima a média aritmética.
       
      #include <stdio.h>
      #include <stdlib.h>
      main () {
      float n1,n2,n3,media;
      printf(" digite a primeira nota");
      scanf("%f" & n1);
      printf("digite a segunda nota"); 
      scanf("%f" & n2);
      printf("digite a terceira nota");
      scanf("%f" & n3);
      media=n1+n2+n3/5;
      printf("a media foi: %f ",media                
      system("pause");
      return 0;
      }
      progama ficou assim mas esat dando o seguinte erros:

      7    14    C:\Users\User\Documents\atividade 2.cpp    [Error] invalid operands of types 'const char [3]' and 'float' to binary 'operator&'
      9    14    C:\Users\User\Documents\atividade 2.cpp    [Error] invalid operands of types 'const char [3]' and 'float' to binary 'operator&'
      11    14    C:\Users\User\Documents\atividade 2.cpp    [Error] invalid operands of types 'const char [3]' and 'float' to binary 'operator&'
      15    1    C:\Users\User\Documents\atividade 2.cpp    [Error] expected ')' before 'system'
       
      agradeço ajuda desde já. obrigada
       
    • Por alyssonw2silva
      Sou novo aqui e estou com o seguinte código 
      function buscar($query) { include_once 'conn.php'; if ($resulte2 = mysqli_query($conn, $query)) { while($row2 = mysqli_fetch_array($resulte2)) { print "<option value='".$row2[0]."'>".$row2[1]."</option>"; }; }; ele e para preencher os campos do meu select está funcionando mas como tenho outro select o primeiro roda agora o segundo da erro quando eu desabilito o primeiro  o segundo select e preenchido 
       
      estou chamando a mesma função para ambos os selects mas o parâmetro $query e diferente 
       
    • Por kaiquefigui
      sempre que uso o comando 'insert into cliente values...' diz que minha query foi atualiza e as linhas foram afetadas porem quando utilizo o comando 'desc cliente' não vejo alterações, como posso resolver esse problema?
      CREATE TABLE CLIENTE( NOME VARCHAR(30), SEXO CHAR(1), CPF CHAR(11), EMAIL VARCHAR(50), TELEFONE VARCHAR(30), ENDEREÇO VARCHAR(100) ); SHOW TABLES; DESC CLIENTE; INSERT INTO CLIENTE VALUES('KAUAN','M','23453678911','KAUAN@HOTMAIL.COM','254896534','ANTONIO HERDEIRO - SÃO PAULO - SP'); INSERT INTO CLIENTE VALUES('ADRIANA','F','24587630894','ADRIANA@HOTMAIL.COM','48652479','ANTONIO HERDEIRO - SÃO PAULO - SP'); INSERT INTO CLIENTE VALUES('KAIQUE','M','34221176809','KAIQUE@HOTMAIL.COM',NULL,'ANTONIO HERDEIRO - SÃO PAULO - SP'); INSERT INTO CLIENTE(NOME,SEXO,CPF,EMAIL,TELEFONE,ENDEREÇO) VALUES('MARCELA','F','15489652011','MARCELO@HOTMAIL.COM','245826157','ANTONIO HERDEIRO - SÃO PAULO - SP');  
    • Por Eduarda Lang Duarte
      O windows diz que não pode encontrar programas da Office 2010, eu ja tentei ir no Regedit e renomear o Office como Office.old e não funcionou, tentei reparar mas sempre aparece que não acha uma dll diferente. Eu já vi várias pessoas com o mesmo problema que eu, e disseram que é vírus, como eu resolvo? É minha primeira vez nesse site, se tiver algo errado, me falem que eu arrumo.
    • Por isaque_cb2
      Boa noite, estou postando qui por que pesquisei e não achei nada que ajudasse... bem, criei um banco de dados para armazenar meus projetos e carrega-los dinamicamente com o php, deu certo, mas quando tem alguma acentuação no texto ele retorna "�"... 
      ~Grato desde Já~
×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.