C não sabe fazer conta [RESOLVIDO]

1. C não sabe fazer conta [RESOLVIDO]

Rafael Sampaio
9u31220

(usa Linux Mint)

Enviado em 23/04/2014 - 18:00h

Fala galera do VOL.

Seja o seguinte código:


#include<stdio.h>
#include<stdlib.h>
#include<math.h>

int main(){

FILE *in;
float num=0,decimal=0,numero1,numero2,multiplicacao;
char c;
int ponto=0;

in=fopen("file.in","r");

while(isdigit(c=getc(in))||c=='.'){

if(c=='.')ponto++;
else if(ponto)decimal+=(c-'0')/pow(10,ponto++);
else num=10*num+c-'0';

}

numero1=num+decimal;
num=decimal=0;
ponto=0;

while(isdigit(c=getc(in))||c=='.'){

if(c=='.')ponto++;
else if(ponto)decimal+=(c-'0')/pow(10,ponto++);
else num=10*num+c-'0';

}

numero2=num+decimal;
multiplicacao=numero1*numero2;

printf("numero1=%.8f numero2=%.8f multiplicacao=%.8f\n",numero1,numero2,multiplicacao);
}


com o seguinte arquivo de entrada file.in:


478.376,2.444


Quando eu compilo e rodo (ps: tem que usar o -lm para compilar) eu recebo a seguinte saída:
numero1=478.37600708 numero2=2.44400001 multiplicacao=1169.15100098

que obviamente está errada, ele acrescentou dígitos decimais depois dos informados no arquivo em numero1 e numero2, numero1 no arquivo é 478.376 e ele pegou 478.37600708 e numero2 no arquivo é 2.444 e ele pegou 2.44400001, provavelmente problema de arredondamento.

O pior de tudo está na multiplicação, esse não é o resultado correto nem para os números originais no arquivo nem para os que o programa pegou. Para os números do arquivo o resultado seria 1169.150944 e para os números no programa o resultado seria 1169,150966087.

Os erros só aparecem nas casas decimais mas infelizmente para a minha aplicação as casas decimais são importantíssimas até muitas casas. Alguém tem alguma idéia de como contornar o problema? Acho que vou abandonar o c.

Obrigado.


  


2. Re: C não sabe fazer conta [RESOLVIDO]

???
gokernel

(usa Linux Mint)

Enviado em 23/04/2014 - 20:23h

@9u31220:
"Acho que vou abandonar o c."

Qual seria o motivo???


Certa vez comigo instalei o DELPHI e em 15 minutos testando ... resolvi: "vou apagar essa porcaria, por nao saber usar" ... eu estava errado.

Depois de tentar mais um pouco e conhecer a ferramenta vi que o DELPHI foi a melhor IDE/ambiente que usei ate hoje.

MORAL, conheça primeiro de verdade e depois decida.



3. Re: C não sabe fazer conta [RESOLVIDO]

Rafael Sampaio
9u31220

(usa Linux Mint)

Enviado em 23/04/2014 - 21:53h

Eu uso C há uns 7 anos, apesar de não saber tudo nem ser um expert eu conheço bem a linguagem.

Motivos existem, se fosse em python por exemplo não precisaria me preocupar com o tamanho das variáveis e a quantidade de casas decimais e teria estruturas de dados mais poderosas já implementadas.

Mas no geral existem linguagens mais produtivas que o C, a começar pelo C++. Depois desse problema então que eu desanimei mais.

A propósito já descobri o problema, era o tamanho do float, se eu usar long double resolve o problema, vou marcar como resolvido.


4. Re: C não sabe fazer conta [RESOLVIDO]

Luis R. C. Silva
luisrcs

(usa Linux Mint)

Enviado em 24/04/2014 - 06:54h

9u31220 escreveu:

Eu uso C há uns 7 anos, apesar de não saber tudo nem ser um expert eu conheço bem a linguagem.

Motivos existem, se fosse em python por exemplo não precisaria me preocupar com o tamanho das variáveis e a quantidade de casas decimais e teria estruturas de dados mais poderosas já implementadas.

Mas no geral existem linguagens mais produtivas que o C, a começar pelo C++. Depois desse problema então que eu desanimei mais.

A propósito já descobri o problema, era o tamanho do float, se eu usar long double resolve o problema, vou marcar como resolvido.


Exatamente, qualquer linguagem moderna possui estruturas mais poderosas implementadas, em C, como você deve saber.

A questão é que C é a linguagem mãe; e quem quiser estruturas melhoradas, tem que implementar mesmo.

Esse problema com ponto flutuante não é com a linguagem, mas sim com a numeração binária. C faz as contas em binário e depois converte para decimal (se quiser faça o teste: divida ou multiplique números decimais com muitas casas decimais manualmente, depois converta para binário; em seguida faça a operação com os binários, depois converta para decimal).

Como o tipo float tem pouca precisão, vai dar um probleminha no final da cadeia numérica. Aumentando a precisão para long double, apenas empurrou o problema para mais longe das casas decimais.

Se quer realmente resolver isso, terá que implementar ou se conformar com o que conseguiu. Aqui no VOL, se não me engano tem um artigo sobre numerais gigantes em C, só não lembro se contempla casas decimais.

Já as outras linguagens, a implementação já ocorreu. Por isso que é errado comparar linguagens, como por exemplo, C com Python. Lógico que Python tem mais recursos, mas esses recursos foram implementados em C, já que Python foi escrita em C. O que quer dizer que, na verdade, tudo que se pode fazer em Python, se pode fazer em C, é só implementar.


5. Re: C não sabe fazer conta [RESOLVIDO]

Rafael Sampaio
9u31220

(usa Linux Mint)

Enviado em 24/04/2014 - 10:38h

rei_astro escreveu:

9u31220 escreveu:

Eu uso C há uns 7 anos, apesar de não saber tudo nem ser um expert eu conheço bem a linguagem.

Motivos existem, se fosse em python por exemplo não precisaria me preocupar com o tamanho das variáveis e a quantidade de casas decimais e teria estruturas de dados mais poderosas já implementadas.

Mas no geral existem linguagens mais produtivas que o C, a começar pelo C++. Depois desse problema então que eu desanimei mais.

A propósito já descobri o problema, era o tamanho do float, se eu usar long double resolve o problema, vou marcar como resolvido.


Exatamente, qualquer linguagem moderna possui estruturas mais poderosas implementadas, em C, como você deve saber.

A questão é que C é a linguagem mãe; e quem quiser estruturas melhoradas, tem que implementar mesmo.

Esse problema com ponto flutuante não é com a linguagem, mas sim com a numeração binária. C faz as contas em binário e depois converte para decimal (se quiser faça o teste: divida ou multiplique números decimais com muitas casas decimais manualmente, depois converta para binário; em seguida faça a operação com os binários, depois converta para decimal).

Como o tipo float tem pouca precisão, vai dar um probleminha no final da cadeia numérica. Aumentando a precisão para long double, apenas empurrou o problema para mais longe das casas decimais.

Se quer realmente resolver isso, terá que implementar ou se conformar com o que conseguiu. Aqui no VOL, se não me engano tem um artigo sobre numerais gigantes em C, só não lembro se contempla casas decimais.

Já as outras linguagens, a implementação já ocorreu. Por isso que é errado comparar linguagens, como por exemplo, C com Python. Lógico que Python tem mais recursos, mas esses recursos foram implementados em C, já que Python foi escrita em C. O que quer dizer que, na verdade, tudo que se pode fazer em Python, se pode fazer em C, é só implementar.


O artigo ao qual se refere deve ser esse :http://www.vivaolinux.com.br/artigo/Programacao-com-numeros-inteiros-gigantes
só para inteiros infelizmente.

Para implementar precisão arbitrária em C é um algoritmo trabalhoso. Com o long double já consigo as 7 casas decimais corretas de que preciso mas vou pesquisar alguma biblioteca pronta só pra brincar.

O C é fundamental, de um certo ponto de vista o Assembly é até mais importante por que com ele dá pra implementar o C e tudo que vem acima dele. Não estou desmerecendo o C e concordo que ele pode ser útil principalmente para implementar coisas novas. Outra área importante do C é em aplicações que interagem com o hardware e precisam de controle de baixo nível. Mas para programação ordinária existem linguagens que já fizeram partes do trabalho, são mais produtivas e poupam trabalho e tempo.



6. Re: C não sabe fazer conta [RESOLVIDO]

Luis R. C. Silva
luisrcs

(usa Linux Mint)

Enviado em 24/04/2014 - 14:31h

Era esse artigo mesmo. Só não lembrava que era apenas para inteiros. De qualquer forma deve haver uma biblioteca que ajude nessa questão de ponto flutuante.


7. Re: C não sabe fazer conta [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 24/04/2014 - 17:42h

O padrão usado nos nossos PCs para a representação de números em ponto flutuante é o IEEE-754. A versão original só previa representações binárias de precisão simples (equivalente, no C, ao float) ou dupla (double do C).

Houve uma revisão do padrão em 2008, que incluiu mais um formato binário e dois formatos decimais. Depende de suporte do hardware e/ou das bibliotecas e compiladores.

As informações sobre o IEEE-754 na Wikipedia (em Inglês) são interessantes. Recomendo sua leitura.






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts