[Pascal] wydawanie reszty - maly blad

0

Błąd jest nastepujcy gdy wpisze np. 4.1 to nie wychodzi mi 2 2 0,1 tylko 2 2 0,05 0,02 0,02 . Prosze o pomoc.
Oto mój programik.

uses crt ;

var
k,n:real;
a:array[1..14] of real;
i,j,x:integer;

procedure uzup;
begin
a[1]:=0.01;
a[2]:=0.02;
a[3]:=0.05;
a[4]:=0.1;
a[5]:=0.2;
a[6]:=0.5;
a[7]:=1;
a[8]:=2;
a[9]:=5;
a[10]:=10;
a[11]:=20;
a[12]:=50;
a[13]:=100;
a[14]:=200;
end;

begin
clrscr;
uzup;
writeln('Podaj reszte');
readln(k);
x:=0 ;
for i:=14 downto 1 do
        if k>=a[i] then break;

for j:=i downto 1 do
begin
        repeat
        if k>=a[j] then
        begin
                k:=k-a[j];
                x:=x+1;
                write(a[j]:3:2,'zł ');
        end;
        until a[j]>k;

end;
writeln;
writeln(x,' potrzbnych monet');

readln;
end.

0
clrscr;
uzup;
writeln('Podaj reszte');
readln(k);
x := 0;
while k > 0 do
begin
  i := 1;
  while (k >= a[i]) and (i < 15) do
    Inc(i);
  Dec(i);
  write(a[i]:3:2,'zł ');
  k := k - a[i];
  Inc(x);
end;
0

Misiekd: a przetestowałeś swoj kod dla liczb ułamkowych, bo na przykłąd po podaniu jako K 4.1 albo 1.3 to
program nie kończy się tylko wywala na ekran dużo cyfr na ekranie i tak w kółko. A na pewno kompilowałem
Twój kod i robiłem to pod Dev-Pascalem. Ja wprawdzie sam nie mam pomysłu jak to poprawić. Pisałem, ale
w Delphi kiedyś program, który to "rozbija" podaną kwotę na mniejsze, ale używając jak najmniejszej ilosći
monet czyli po podaniu kwoty - na przykład 457,53 wyświetli taki rezultat jak poniżej. Jeżeli Ciebie Dunajal
interesuje ten kod to moge zapodać, da się pozbywając się idiotoodporności programu, skompilować go też
pod TurboPascalem, ale używa on funkcji Round oraz Trunc, które o ile wiem, dostępne są w Turbo Pascalu.

Kwota: 457,33 to:
2*200 zł
1*50 zł
1*5 zł
1*2 zł
1*20 gr
1*10 gr
1*2 gr
1*1 gr
0

spróbuje zrobic to przez dzielenie , zobaczymy co z tego bedzie.

0

to trzeba zamienić warunek w pętli na coś takiego

(k - a[i] > -0.00001)

BTW nie powinno się porównywać liczb zmienno przecinkowych tak jak to jest w pierwszym moim poście bo są potem problemy :p

0

taki troche offtop. Dunajal nie uzywasz zmiennej n ktora masz zadeklarowaną. zawsze to oszczednosc kilku bajtów :)

0

Dzięki Misiekd twoj programik smiga aż miło :D.
Gdyby ktoś znalaz powód przez który mój pierwszy program nie dziala proszę pisać na forum. W środe mam informatyke to sie babki zapytam może bedzie wiedzieć co jest nie tak.

aigimig napisał(a)

taki troche offtop. Dunajal nie uzywasz zmiennej n ktora masz zadeklarowaną. zawsze to oszczednosc kilku bajtów :)

Myślę ze przy dzisiejszych komputerach to nie stanowi problemu :p

0
dunajal napisał(a)

Myślę ze przy dzisiejszych komputerach to nie stanowi problemu :p

tak mawiaja w microsofcie ;]

0

Kwoty lepiej przechowywać w groszach, i wtedy nie real tylko longint. 457,33 zł to 45733 grosze i na takich liczbach całkowitych powinien program operować.
Na zmiennych rzeczywistych będą się cuda działy.

0
Azarien napisał(a)

Kwoty lepiej przechowywać w groszach, i wtedy nie real tylko longint. 457,33 zł to 45733 grosze i na takich liczbach całkowitych powinien program operować.
Na zmiennych rzeczywistych będą się cuda działy.

mi tez sie wydaje, ze lepiej na groszach operowac...
tu kod w Delphi ale mysle ze kazdy sobie poradzi z przerobieniem na pascala:

var moneta:array[1..14] of Word;
    doWydania:LongWord;
    i:Byte;
    x:Word;
begin
moneta[1]:=1; //1gr
moneta[2]:=2; //2gr
moneta[3]:=5; //5gr
moneta[4]:=10; //10gr
moneta[5]:=20; //20gr
moneta[6]:=50; //50gr
moneta[7]:=100; //1zl
moneta[8]:=200; //2zl
moneta[9]:=500; //5zl
moneta[10]:=1000; //10zl ***
moneta[11]:=2000; //20zl ***
moneta[12]:=5000; //50zl ***
moneta[13]:=10000; //100zl ***
moneta[14]:=20000; //200zl ***
{...}
doWydania:=LongWord( trunc(1028.71 * 100)); //tak "na razie"... :)
{...}
for i:=14 downto 1 do
        begin
        x:=(doWydania div moneta[i]);//ile monet/banknotow sie miesci w kwocie do wydania
        if x>0 then
                begin
                ListBox1.Items.Add(inttostr(x)+'x '+floattostr(moneta[i] / 100)+'zł');
                doWydania:=DoWydania-(moneta[i]*x);
                end;
        end;
end;

dodatkowo mozna dodac kilka linijek kodu:

for i:=14 downto 1 do
        begin
        x:=(doWydania div moneta[i]);//ile monet/banknotow sie miesci w kwocie do wydania
        if liczbaMonet[i]<x
                then continue;
        if x>0 then
                begin
                ListBox1.Items.Add(inttostr(x)+'x '+floattostr(moneta[i] / 100)+'zł');
                doWydania:=DoWydania-(moneta[i]*x);
                liczbaMonet[i]:=liczbaMonet[i]-x;
                end;
        end;
if doWydania=0
        then ListBox1.Items.Add('Wydaj reszte')
        else ListBox1.Items.Add('Nie da sie wydac reszty, zwroc pieniadze.');

i mozemy przy wydawaniu reszty uwzglednic, jesli brakuje (np w automacie) jakis monet czy banknotow. jesli brakuje np 20-sto zlotowych banknotow to program "wyda" 2x10zl.

0

tu kod w Delphi ale mysle ze kazdy sobie poradzi z przerobieniem na pascala:

Akurat jedyną ściśle Delphiową (ale też Lazarusową) rzeczą w tym kodzie jest ListBox1... Mam wrażenie, że na forum zbyt ściśle rozróżnia się Delphi od Pascala.

0
Azarien napisał(a)

tu kod w Delphi ale mysle ze kazdy sobie poradzi z przerobieniem na pascala:

Akurat jedyną ściśle Delphiową (ale też Lazarusową) rzeczą w tym kodzie jest ListBox1... Mam wrażenie, że na forum zbyt ściśle rozróżnia się Delphi od Pascala.

oraz floattostr, inttostr i LongWord ;]

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