Ir ao conteúdo
  • Cadastre-se

C O código funciona mais deixa 0.01 no float sempre


Arthur_Azvd

Posts recomendados

Sou iniciante em programação em C e estou com uma duvida nesse código, ele basicamente calcula a menor quantidade de moedas que serão utilizadas para dar troco ao usuário, o código tá funcionando e tal, mas ele sempre deixa um resto de 0.01 que é correspondente a 1 centavo e eu não sei como fazer com que ele não deixe mais esse resto.

Se alguém souber como fazer isso por favor me ajudem.

 

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

int
main(void)
{
	//Pergunta ao usuario o troco que ele tem que receber
	printf("quanto de troco você quer receber? \n");
	float troco = GetFloat();
	//variavel usada no While
	int fim = 1;
	//contador de quantas moedas vão ser necessarias
	int contador = 0;
	
	// Loop que vai calcular a menor quantidade de moedas para o troco do cliente
	do
	{
	if(troco >= 0.25){
	contador++;
	troco = troco - 0.25;

	} else if (troco >= 0.10){
	contador++;
	troco = troco - 0.10;

	} else if (troco >= 0.05){
	contador++;
	troco = troco - 0.05;
	
	} else if (troco >= 0.010){
	contador++;
	troco = troco - 0.01;

	} else{
	fim = 0;
	}
}
	while(fim == 1);
	
	//imprimi a quantidade de moedas que o while calculou
	printf("%d\n",contador);
	
}

 

cc50_c_library.zip

  • Amei 1
Link para o comentário
Compartilhar em outros sites

@Arthur_Azvd @Arthur_Azvd    não sei por quê , mais seu código não está funcionando !  ,  e creio que seja aquela atribuição no final que esteja causando esse erro , e então seu código com algumas modificações poderia ser assim  :

//#include <cc50.h> //  esse aqui não se encontra nesse código , por isso não funciona não
#include <stdio.h>
#include <stdlib.h>
int main(){ // não precisa colocar esse Void não
    float troco;  // criei essa variável depois
	//Pergunta ao usuario o troco que ele tem que receber
	printf("quanto de troco você quer receber? \n");
	//float troco = GetFloat();
	scanf("%f",&troco);
	//variavel usada no While
	int fim = 1;
	//contador de quantas moedas vão ser necessarias
	int contador = 0;
	// Loop que vai calcular a menor quantidade de moedas para o troco do cliente
	do{
        if(troco >= 0.25){
            contador++;
            troco = troco - 0.25;
        }
        else  // não existe ElseIf na linguagem c
            if(troco >= 0.10){// só existe o Else  e o  If
	            contador++;
	            troco = troco - 0.10;
	        }
            else
                if( troco >= 0.05 ){
                    contador++;
                    troco = troco - 0.05;
                }
                else
                    if( troco >= 0.010 ){
                        contador++;
                        troco = troco - 0.01;// aqui pode ser a causa de sempre deixar 0,01
                    }
                    else{
                        fim = 0;
                    }
    }
	while(fim == 1);// esse comoando aqui é Demais , pois ele não fará nada ?
	//imprimi a quantidade de moedas que o while calculou
	printf("%d\n",contador);
	return 32768;  //  geralmente retorna alguma coisa pois a função é int main
}

 

  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

Use centavos como unidade e não como 0.01 e calcule tudo usando int. 

 

Usar float e double sempre inclui um risco de erro de arredondamento e sobra algo. E quando compara muitas vezes não dá igual porque na representação interna de dois float eles podem diferir por algum valor lá na oitava casa decimal por exemplo, devido à representação não ser exata.

 

Por isso COBOL foi a linguagem do dinheiro por décadas: contas sem erro de arredondamento.

  • Curtir 1
  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

@Arthur_Azvd Usou uma função dessa tal biblioteca cc50.h só pra ler um float? Não é mais fácil só usar scanf(), e declarar uma variável no mínimo do tipo double ao invés de float? Com double a precisão é maior, mas você ainda pode ter problemas com isso, não é bom trabalhar com números tão pequenos.

Não esqueça de incluir a biblioteca locale.h para possibilitar imprimir acentuação. Indentação também é importante.

 

Teste isso:

#include <stdio.h>
#include <locale.h>

int main()
{
    setlocale(LC_ALL, "Portuguese");
    long double troco;
    //Pergunta ao usuario o troco que ele tem que receber
    printf("quanto de troco você quer receber? \n");
    scanf("%Lf", &troco);
    //variavel usada no While
    int fim = 1;
    //contador de quantas moedas vão ser necessarias
    int contador = 0;
	
    // Loop que vai calcular a menor quantidade de moedas para o troco do cliente
    do{
    	if(troco >= 0.25){
    	    contador++;
    	    troco -= 0.25;
    	}else if (troco < 0.25 && troco >= 0.1){
    	    contador++;
    	    troco -= 0.10;
    	}else if (troco < 0.10 && troco >= 0.05){
    	    contador++;
    	    troco -= 0.05;
    	}else if (troco < 0.05 && troco >= 0.009){
    	    contador++;
    	    troco -= 0.01;
    	}else{
    	    fim = 0;
    	}
    }while(fim == 1);
	
    //imprimi a quantidade de moedas que o while calculou
    printf("%d\n",contador);
	
}

 

  • Obrigado 2
Link para o comentário
Compartilhar em outros sites

O seu código está comparando `floats` com `doubles` literais, o que não é recomendado. O compilador pode até resolver isso para você, mas o padrão é que o `double` literal seja convertido implicitamente, truncando o valor representado e causando um erro de arredondamento minúsculo que se acumula com as múltiplas operações realizadas. Se o `double` está disponível, faça os cálculos e comparações todos em `double`, apesar que comparações de igualdade tipicamente não funcionam como esperado em ponto flutuante binário.

 

Cálculo com ponto flutuante binário e erros de arredondamento andam juntos e são esperados, mas isso não é o caso em se tratando de dinheiro. Há alguns processadores que suportam ponto flutuante decimal em hardware, mas a estratégia mais comum que já vi envolve usar inteiros com ou sem sinal e escalas (acho que a classe `BigDecimal` do Java funciona assim). Se o problema não envolvesse decimais e aceitasse binários, poderia usar, isto é, implementar, em ponto fixo, já que o suporte no compilador é uma extensão do GCC não compatível com todas as arquiteturas.

 

Leitura interessante:
https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/

Versão longa e muito mais detalhada (até hoje não terminei de ler):

https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

  • Curtir 1
  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

Imprecisão: Fração Decimal --> Binário

 

Por conta da imprecisão ao representar frações de décimos em binários; conclui-se, por exemplo, que 0.01 é representado não exatamente 1/100; E a propagação dessa imprecisão aumenta na medida das operações ou que no final o valor 0.01 restante na variável é ≅ 0.0099...d

 

  • Curtir 1
  • Obrigado 2
Link para o comentário
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisa ser um usuário 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

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...