Problem konwersją int->double (chyba)

0

Mam problem z prostym programem.
Za zadanie ma obliczać w jaki sposób rozmienić pewną kwotę, mając dostępną ograniczoną ilość monet. Program działa w sumie prawidłowo, za wyjątkiem tego, że dla małych liczb (poniżej 10zł) zawsze ucina ostatni grosz. Podczas debug zauważyłem, że poniżej 5zł zaczyna odejmować (lub dodawać dla kwot powyżej 10zł) coś na 15-16 miejscu po przecinku. Z każdą operacją różnica rośnie geometrycznie.
Nie wiem czy to problem konwersji czy czegoś innego. Stąd proszę o pomoc.
Oto kod programu.

public class Monety {

	public static void main(String[] args) {
		int[] tabelaIlosci = { 1, 3, 5, 10, 20, 200, 100, 100, 10000 };
		String[] tabelaOpisow = { "5zł", "2zł", "1zł", "50gr", "20gr", "10gr",
				"5gr", "2gr", "1gr" };
		double[] tabelaWartosci = { 5, 2, 1, 0.5, 0.2, 0.1, 0.05, 0.02, 0.01 };

		double cena = 9.51; //tutaj wpisuję cenę, nie ma żadnego mechanizmu wsadu
		System.out.println("Wydaj "+cena+":");

		for (int komórkaTabeli = 0; komórkaTabeli < tabelaIlosci.length; komórkaTabeli++) {
			int ilośćMonet = (int) (cena / tabelaWartosci[komórkaTabeli]);
			if (ilośćMonet > 0 && tabelaIlosci[komórkaTabeli] > ilośćMonet) {
				tabelaIlosci[komórkaTabeli] = tabelaIlosci[komórkaTabeli]
						- ilośćMonet;
				System.out.println("Wydaj " + ilośćMonet + " monety "
						+ tabelaOpisow[komórkaTabeli]);
			} else if (ilośćMonet > 0 && tabelaIlosci[komórkaTabeli]>0) {
				ilośćMonet = tabelaIlosci[komórkaTabeli];
				tabelaIlosci[komórkaTabeli] = 0;
				System.out.println("Wydaj " + ilośćMonet + " monety "
						+ tabelaOpisow[komórkaTabeli]);
			}
			cena = cena - (ilośćMonet * tabelaWartosci[komórkaTabeli]);
		}
		System.out.println("Koniec");
		System.exit(-1);
	}
}

Pozdrawiam.

1

Niech tabela wartości będzie trzymać kwoty w groszach, a nie ułamkach złotówki. Obliczeń finansowych NIE WOLNO wykonywać na liczbach zmiennoprzecinkowych.

0

Faktycznie, pomnożenie wartości w tabeliWartosci oraz ceny wyeliminowało błąd. Dziękuję.
Czy mogę jeszcze prosić o wyjaśnienie czemu tak się dzieje? Chciałbym unikać podobnych błędów w przyszłości. Najchętniej dzięki wiedzy a nie przyzwyczajeniu.

Pozdrawiam.

1

ułamki mające w liczniku coś innego od potęgi dwójki (np. 0.2) mają nieskończoną reprezentację binarną, z tego powodu muszą pojawiać się błędy zaokrągleń.

1

Liczby zmiennoprzecinkowe nie są precyzyjne. Komputer nie odwzoruje prawidłowo np. 1/3 jako zapisu 0.3(3). W pewnym momencie (na tym 15-16 miejscu) utnie precyzję. Liczby całkowite są znacznie wygodniejsze, bo zachowują precyzję.

1 użytkowników online, w tym zalogowanych: 0, gości: 1