Enunciado:
Leia um valor de ponto flutuante com duas casas decimais. Este valor representa um valor monetário. A seguir, calcule o menor número de notas e moedas possíveis no qual o valor pode ser decomposto. As notas consideradas são de 100, 50, 20, 10, 5, 2. As moedas possíveis são de 1, 0.50, 0.25, 0.10, 0.05 e 0.01. A seguir mostre a relação de notas necessárias.
Acredito que meu código esteja certo, porém acho que estou esbarrando naquele velho problema da programação da aritmética com ponto flutuante, onde os resultados das operações não são exatos, o que compremete no meu algoritmo. Tentei usar o BigDecimal, porém ainda sim o problema persiste.
package principal;
import java.math.BigDecimal;
import java.util.Scanner;
public class CalculoDasNotas2 {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int numeroNotasDe100 = 0;
int numeroNotasDe50 = 0;
int numeroNotasDe20 = 0;
int numeroNotasDe10 = 0;
int numeroNotasDe5 = 0;
int numeroNotasDe2 = 0;
int numeroNotasDe1 = 0;
int numeroMoedasDe50 = 0;
int numeroMoedasDe25 = 0;
int numeroMoedasDe10 = 0;
int numeroMoedasDe5 = 0;
int numeroMoedasDe1 = 0;
BigDecimal valor = new BigDecimal(scan.nextDouble());
for(int i = (int) valor.doubleValue(); i >= 100; i -= 100) {
valor = valor.subtract(new BigDecimal(100));
numeroNotasDe100++;
}
for(int i = (int) valor.doubleValue(); i >= 50; i -= 50) {
valor = valor.subtract(new BigDecimal(50));
numeroNotasDe50++;
}
for(int i = (int) valor.doubleValue(); i >= 20; i -= 20) {
valor = valor.subtract(new BigDecimal(20));
numeroNotasDe20++;
}
for(int i = (int) valor.doubleValue(); i >= 10; i -= 10) {
valor = valor.subtract(new BigDecimal(10));
numeroNotasDe10++;
}
for(int i = (int) valor.doubleValue(); i >= 5; i -= 5) {
valor = valor.subtract(new BigDecimal(5));
numeroNotasDe5++;
}
for(int i = (int) valor.doubleValue(); i >= 2; i -= 2) {
valor = valor.subtract(new BigDecimal(2));
numeroNotasDe2++;
}
for(int i = (int) valor.doubleValue(); i >= 1; i--) {
valor = valor.subtract(new BigDecimal(1));
numeroNotasDe1++;
}
for(BigDecimal i = valor; i.doubleValue() >= 0.5; i = i.subtract(new BigDecimal(0.5))) {
valor = valor.subtract(new BigDecimal(0.5));
numeroMoedasDe50++;
}
for(BigDecimal i = valor; i.doubleValue() >= 0.25; i = i.subtract(new BigDecimal(0.25))) {
valor = valor.subtract(new BigDecimal(0.25));
numeroMoedasDe25++;
}
for(double i = valor.doubleValue(); i >= 0.1; i -= 0.1) {
valor = valor.subtract(new BigDecimal(0.1));
numeroMoedasDe10++;
}
for(BigDecimal i = valor; i.doubleValue() >= 0.05; i = i.subtract(new BigDecimal(0.05))) {
valor = valor.subtract(new BigDecimal(0.05));
numeroMoedasDe5++;
}
for(BigDecimal i = valor; i.doubleValue() >= 0.01; i = i.subtract(new BigDecimal(0.01))) {
System.out.println(valor);
valor = valor.subtract(new BigDecimal(0.01));
numeroMoedasDe1++;
}
System.out.println("NOTAS:");
System.out.println(numeroNotasDe100 + " nota(s) de R$ 100.00");
System.out.println(numeroNotasDe50 + " nota(s) de R$ 50.00");
System.out.println(numeroNotasDe20 + " nota(s) de R$ 20.00");
System.out.println(numeroNotasDe10 + " nota(s) de R$ 10.00");
System.out.println(numeroNotasDe5 + " nota(s) de R$ 5.00");
System.out.println(numeroNotasDe2 + " nota(s) de R$ 2.00");
System.out.println("MOEDAS:");
System.out.println(numeroNotasDe1 + " moeda(s) de R$ 1.00");
System.out.println(numeroMoedasDe50 + " moeda(s) de R$ 0.50");
System.out.println(numeroMoedasDe25 + " moeda(s) de R$ 0.25");
System.out.println(numeroMoedasDe10 + " moeda(s) de R$ 0.10");
System.out.println(numeroMoedasDe5 + " moeda(s) de R$ 0.05");
System.out.println(numeroMoedasDe1 + " moeda(s) de R$ 0.01");
scan.close();
}
}
Quando a entrada é 0,97 ao invés dele me retornar que são 2 moedas de 1 centavo, ele me retorna que é apenas 1. Então, gostaria de destacar a seguinte parte do código:
for(BigDecimal i = valor; i.doubleValue() >= 0.01; i = i.subtract(new BigDecimal(0.01))) {
System.out.println(valor);
valor = valor.subtract(new BigDecimal(0.01));
numeroMoedasDe1++;
}
Na parte do “System.out.println(valor);” ele deveria imprimir na tela um 0.2, mas ao invés disso sai o 0.0199999999999999622524171627446776255965232849121093750, então o for só executado uma vez (já que depois de executado uma vez, o valor será menor que 0.1) o que faz com que a variável “numeroMoedasDe1” seja incrementada apenas uma vez, e não duas.
Tendo tudo isso em vista, como faço para resolver esse problema?