Programa Java - Calcular troco com notas e moedas

Ola para todos

Estou fazendo um programa para calcular o troco para informar quanto vai devolver notas e moedas, mas o codigo que fiz nao esta dando certo, estou bem confuso, alguem poderia me ajudar ?

import java.util.List;

public interface IMaquina {
List montarTroco(double troco);
}

public class Troco {
public enum ECedula {
NOTA100(100), NOTA50(50), NOTA20(20), NOTA10(10), NOTA5(5), NOTA2(2), MOEDA100(
1), MOEDA50(0.5), MOEDA25(0.25), MOEDA10(0.1), MOEDA5(0.05), MOEDA1(
0.01);
ECedula(double valor) {
this.valor = valor;
}
private double valor;
public double getValor() {
return valor;
}
}

private ECedula tipo;
private int quantidade;

public void adicionaQuantidade(int qtde) {
	quantidade += qtde;
}

public Troco(ECedula tipo, int quantidade) {
	super();
	this.tipo = tipo;
	this.quantidade = quantidade;
}

public ECedula getTipo() {
	return tipo;
}

public int getQuantidade() {
	return quantidade;
}

@Override
public String toString() {
	return quantidade + " - " + tipo;
}

}

import java.text.DecimalFormat;
import java.util.List;

public class CalculaTroco implements IMaquina {

@Override
public List<Troco> montarTroco(double troco) {
	
	DecimalFormat formatador = new DecimalFormat("###,##0.00");
   

      String result;
      double Vtroco;
      int i, vlr, ct;

      //Vtroco = pago - conta;
      result ="\nTroco = R$"+ formatador.format(Vtroco) +"\n\n";

// definindo as notas do troco (parte inteira)
      
      vlr = (int)Vtroco;
      i = 0;
      while (vlr != 0) {
        ct = vlr / nota[i]; // calculando a qtde de notas
        if (ct != 0) {
           result = result + (ct +"nota(s) de R$"+ nota[i] +"\n");
           vlr = vlr % nota[i]; // sobra
        }
        i = i + 1; // próxima nota
      }

      result = result +"\n";

// definindo os centavos do troco (parte fracionária)
      
      vlr = (int)Math.round((Vtroco - (int)Vtroco) * 100);
      i = 0;
      while (vlr != 0) {
        ct = vlr / centavos[i]; // calculando a qtde de moedas
        if (ct != 0) {
           result = result + (ct +"moeda(s) de"+ centavos[i] +
           "centavo(s)\n");
           vlr = vlr % centavos[i]; // sobra
        }
        i = i + 1; // próximo centavo
      }

      return(result);
    }


}

Como é que você conta as cédulas e moedas para dar um troco no mundo real?
Comece verificando das cédulas e moedas maiores para as menores.

package com.senior.avaliacao.qs7;

import static com.senior.avaliacao.qs7.ECedula.*;

import java.util.LinkedList;
import java.util.List;

public class CalculaTroco implements IMaquina {

	public static void main(String[] args) {
		double valor = 1879.48;
		CalculaTroco calculadora = new CalculaTroco();
		System.out.printf("Valor troco: %.2f%n", valor);
		for (Troco troco : calculadora.montarTroco(valor)) {
			System.out.println(troco);
		}
	}

	@Override
	public List<Troco> montarTroco(double valor) {
		List<Troco> result = new LinkedList<>();

		valor = contarCedulas(NOTA100, valor, result);
		valor = contarCedulas(NOTA50, valor, result);
		valor = contarCedulas(NOTA20, valor, result);
		valor = contarCedulas(NOTA10, valor, result);
		valor = contarCedulas(NOTA5, valor, result);
		valor = contarCedulas(NOTA2, valor, result);
		valor = contarCedulas(MOEDA100, valor, result);
		valor = contarCedulas(MOEDA50, valor, result);
		valor = contarCedulas(MOEDA25, valor, result);
		valor = contarCedulas(MOEDA10, valor, result);
		valor = contarCedulas(MOEDA5, valor, result);
		valor = contarCedulas(MOEDA1, valor, result);

		return result;
	}

	private double contarCedulas(ECedula cedula, double valor, List<Troco> result) {
		Troco troco = new Troco(cedula, 0);
		while (valor >= cedula.getValor()) {
			troco.adicionaQuantidade(1);
			valor -= cedula.getValor();
		}
		if (troco.getQuantidade() > 0) {
			result.add(troco);
		}
		return valor;
	}
}
1 curtida

Precisa mesmo de todas essas classes? Um enum pra representas as cédulas e moedas? Bom, claro que dependendo dos requisitos do sistema, pode até ser necessário, mas primeiro eu me concentraria no algoritmo para depois ir complicando. Uma forma simples é ter um array com os valores possíveis das notas e moedas em centavos, e colocando os maiores valores primeiro. Assim, para o troco, basta pegar cada valor e ver quantas notas/moedas de cada você precisa.

Por exemplo, se o valor for 280 reais. Primeiro eu vejo quantas notas de 100 precisa, então bastaria dividir por 280 por 100: o resultado (arredondado) é 2, portanto precisa de 2 notas de 100. Depois eu desconto esse valor e pego o restante, e aí basta pegar o resto da divisão de 280 por 100, que é 80 (para isso usamos o operador %).

Depois vejo a nota seguinte, que é 50, e vejo quantas notas preciso: divido 80 por 50, que dá 1 (ou seja, 1 nota de 50), pego o resto da divisão (que é 30) e vejo a nota seguinte (20) e assim por diante. Ou seja:

// valores das notas e moedas, em centavos
int[] notasMoedas = {10000, 5000, 2000, 1000, 500, 200, 100, 50, 25, 10, 5, 1};

double valorTroco = 1879.48;
// converte o valor para centavos
int valorCentavos = (int) (valorTroco * 100);
Map<Double, Integer> quantidades = new LinkedHashMap<>(); // guardar as quantidades de cada nota/moeda
for (int nota : notasMoedas) {
    if (valorCentavos >= nota) {
        int qtd = valorCentavos / nota; // quantidade da nota/moeda
        quantidades.put(nota / 100.0, qtd);
        valorCentavos %= nota; // pega o resto da divisão, pra ter o valor restante
        if (valorCentavos == 0) {
            break; // se o valor zerou, sai do for (não tem porque continuar)
        }
    }
}

// imprime os resultados
for (Map.Entry<Double, Integer> e : quantidades.entrySet()) {
    double notaMoeda = e.getKey();
    int qtd = e.getValue();
    String tipo;
    if (notaMoeda > 1) {
        tipo = "nota";
    } else {
        tipo = "moeda";
    }
    System.out.printf("%d %s%s de %.2f\n", qtd, tipo, qtd > 1 ? "s" : "", notaMoeda);
}

Pronto, essa é a ideia básica. Agora você pode adaptar e “complicar”, criando uma classe para o troco, um enum para as notas/moedas, etc (que eu acho meio desnecessário, mas enfim, pode ser que seja requisito do exercício, sei lá).

Vale lembrar também que double e float não são adequados para trabalhar com dinheiro (uma opção menos pior é usar int ou long com a quantidade de centavos, pois isso evita os problemas citados nesse link, além de facilitar o cálculo do troco - já que usar o operador % com float, principalmente com números menores que 1, inviabilizaria o algoritmo acima).

Também achei desnecessário essa classe Troco, que nada mais é do que um contador de cédulas…
Mas sabe lá o como é o enunciado do exercício, afinal tem uma interface IMaquina que só define uma operação para montar troco? Meio sem sentido.

Ola tudo bem

Utilizei a sua sugestao, mas o codigo esta apresentando erro neste trecho onde esta declado as moedas e notas:

import java.util.LinkedList;
import java.util.List;

import com.senior.avaliacao.qs7.Troco.ECedula;

public class CalculaTroco implements IMaquina {

@Override
public List<Troco> montarTroco(double valor) {
	List<Troco> result = new LinkedList<>();

	valor = contarCedulas(NOTA100, valor, result);
	valor = contarCedulas(NOTA50, valor, result);
	valor = contarCedulas(NOTA20, valor, result);
	valor = contarCedulas(NOTA10, valor, result);
	valor = contarCedulas(NOTA5, valor, result);
	valor = contarCedulas(NOTA2, valor, result);
	valor = contarCedulas(MOEDA100, valor, result);
	valor = contarCedulas(MOEDA50, valor, result);
	valor = contarCedulas(MOEDA25, valor, result);
	valor = contarCedulas(MOEDA10, valor, result);
	valor = contarCedulas(MOEDA5, valor, result);
	valor = contarCedulas(MOEDA1, valor, result);

	return result;
}

private double contarCedulas(ECedula cedula, double valor, List<Troco> result) {
	Troco troco = new Troco(cedula, 0);
	while (valor >= cedula.getValor()) {
		troco.adicionaQuantidade(1);
		valor -= cedula.getValor();
	}
	if (troco.getQuantidade() > 0) {
		result.add(troco);
	}
	return valor;
}

}

Primeiro tira o ECedula de dentro da classe Troco.
Depois faz o import estático de seus atributos.

Ola seria isso ? Nao entendi muito bem

public class Troco {

	ECedula(double valor) {
		this.valor = valor;
	}
	private double valor;
	public double getValor() {
		return valor;
	}
}

private ECedula tipo;
private int quantidade;

public void adicionaQuantidade(int qtde) {
	quantidade += qtde;
}

public Troco(ECedula tipo, int quantidade) {
	super();
	this.tipo = tipo;
	this.quantidade = quantidade;
}

public ECedula getTipo() {
	return tipo;
}

public int getQuantidade() {
	return quantidade;
}

@Override
public String toString() {
	return quantidade + " - " + tipo;
}

}

import java.util.LinkedList;
import java.util.List;

import com.senior.avaliacao.qs7.Troco.ECedula;

public class CalculaTroco implements IMaquina {

@Override
public List<Troco> montarTroco(double valor) {
	List<Troco> result = new LinkedList<>();

	valor = contarCedulas(NOTA100, valor, result);
	valor = contarCedulas(NOTA50, valor, result);
	valor = contarCedulas(NOTA20, valor, result);
	valor = contarCedulas(NOTA10, valor, result);
	valor = contarCedulas(NOTA5, valor, result);
	valor = contarCedulas(NOTA2, valor, result);
	valor = contarCedulas(MOEDA100, valor, result);
	valor = contarCedulas(MOEDA50, valor, result);
	valor = contarCedulas(MOEDA25, valor, result);
	valor = contarCedulas(MOEDA10, valor, result);
	valor = contarCedulas(MOEDA5, valor, result);
	valor = contarCedulas(MOEDA1, valor, result);

	return result;
}

private double contarCedulas(ECedula cedula, double valor, List<Troco> result) {
	Troco troco = new Troco(cedula, 0);
	while (valor >= cedula.getValor()) {
		troco.adicionaQuantidade(1);
		valor -= cedula.getValor();
	}
	if (troco.getQuantidade() > 0) {
		result.add(troco);
	}
	return valor;
}

}

import static com.senior.avaliacao.qs7.Troco.ECedula.*;

Agora funcionou ! Obrigado pela ajuda vou seguir nos estudos aqui por esse caminho que me orientou !