如何计算变更金额的硬币组合?

时间:2013-08-09 13:52:28

标签: delphi delphi-7 pascal

我正在尝试在Delphi / Pascal中创建一个更改程序。我有价值$ 0.05,$ 0.10,$ 0.20,$ 0.50,$ 1.00和$ 2.00,以及未知金额x。我需要能够给出每个面额构成x金额的硬币数量。无限量的任何面额的硬币,这一点无关紧要。

我已经尝试了5天,但对于我的生活,我没有什么可以表现出来的。我尝试过动态数组,我尝试了for(数组)do,但这对我不起作用。如果你能让我走上正轨,那就太好了!

更新

好的,我已经研究过了,但是现在我遇到了一些我无法弄清楚的问题,这是第一个问题的一部分。我不断得到它不喜欢我的“硬币”的问题。我试图将它设置为一个数组,它不喜欢它,我把它作为一个常量数组尝试然后它不喜欢它,我甚至尝试它作为一个集合,但这不起作用。这应该有用,但我错过了一些东西。任何想法都会很棒!

var
  Form1: TForm1;
  i : integer;
  change : integer;
  coins : double;
  coinage : integer;
begin
  coins := (0.05, 0.10, 0.20, 0.50, 1.00, 2.00);
  change := 4.00;
  while change > 0 do
    coinage := trunc(change/coins);
    change := change-coinage*coins;
    i := change - 1;
    while change>=1 do
    begin
      coinage := 0;
      i := coinage-1;
    end;
  end;

3 个答案:

答案 0 :(得分:1)

您解决问题的方法有点不正确。听起来好像您正在考虑将要使用的数据类型,而不首先考虑问题本身的解决方案。你首先需要的是algorithm,这是一系列动作,在你的情况下产生最终结果 - 每个面额的硬币数量。大约有16种类型的常用算法,而您最有可能解决此问题的方法是dynamic programming,或者如果您不需要获得minimal数量的硬币,但只是得到任何可能的方式来获得硬币加起来x,然后greedy algorithm应该做的伎俩。如果你的算法至少在头脑中,那么考虑你需要的数据类型会更容易。

我不建议你处理算法问题,你在一两天内无法解决,因为这有点令人失望,至少对我来说是这样,除非那被分配为作业或其他东西

答案 1 :(得分:1)

试试这段代码:

type
  TCoin = (cn5, cn10, cn20, cn50, cn100, cn200);
  TCoinValues = array[TCoin] of Currency;
  TMoney = array[TCoin] of Integer;

const
  CoinValues: TCoinValues = (0.05, 0.10, 0.20, 0.50, 1.00, 2.00);
  ZeroMoney: TMoney = (0, 0, 0, 0, 0, 0);

function GetChange(Amount: Currency; out Remainder: Currency): TMoney;
var
  C: TCoin;
  N: Integer;
begin
  Result := ZeroMoney;
  for C := High(TCoin) downto Low(TCoin) do
  begin
    N := Trunc(Amount / CoinValues[C]);
    Amount := Amount - N * CoinValues[C];
    Result[C] := N;
  end;
  Remainder := Amount;
end;

用法:

在表单上删除一个按钮和一个备忘录,并将此事件处理程序分配给Button的OnClick事件:

procedure TForm1.Button1Click(Sender: TObject);
const
  TestAmount = 12.97;
var
  Change: TMoney;
  Remainder: Currency;
  C: TCoin;
begin
  Change := GetChange(TestAmount, Remainder);
  Memo1.Clear;
  Memo1.Lines.Add(Format('%m breaks down into:', [TestAmount]));
  for C := Low(TCoin) to High(TCoin) do
    Memo1.Lines.Add(Format('%d x %m' , [Change[C], CoinValues[C]]));
  Memo1.Lines.Add(Format('%m remains', [Remainder]));
end;

结果:

Screen shot

答案 2 :(得分:0)

从算法的角度来看,这是一个很简单的问题,你不应该遇到任何麻烦。事实上,你总是解决问题,然后你找工具。简单地说,你从最大的金额开始,并在你的名单上计算,直到你用完为止。

然而,Delphi / Pascal在解决这个问题时遇到的一个具体问题是Delphi不支持定点十进制算法(它通过FPU做科学记数法,这对于科学应用来说已经足够了,不适用于会计那些),这意味着你需要提出一个解决方案(有时“货币”类型有效,它会在这里工作)。鉴于你的问题,这很简单 - 你用便士来代替小数单位,并在代码中考虑到。

procedure TForm1.Button1Click(Sender: TObject);
  const
    coins: array[1..6] of integer = (5, 10, 20, 50, 100, 200);
  var
    amount: integer;
    i: integer;
  begin
    amount := trunc(StrToFloat(Edit1.Text)*100);
    Memo1.Clear;
    i := 6;
    while i > 0 do
      begin
        while coins[i] <= amount do
          begin
            Memo1.Lines.Add(FloatToStrF(coins[i] / 100, ffFixed, 18, 2));
            amount := amount - coins[i];
          end;
        dec(i);
      end;
     Memo1.Lines.Add(FloatToStrF(amount / 100, ffFixed, 18, 2) + ' left.');
  end;

在生产代码中,我会针对StrToFloat调用添加一个检查以获得正确的数字输入,但这是您正在寻找解决问题的基本思路。