0

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

我已经尝试了 5 天,但对于我的一生,我没有什么可证明的。我试过动态数组,我试过for(array) 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;
4

3 回答 3

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 和一个备忘录,并将此事件处理程序分配给 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;

结果:

截屏

于 2013-08-11T11:02:04.647 回答
1

您解决问题的方法有点不正确。听起来好像您正在考虑要使用的数据类型,而没有首先考虑问题本身的解决方案。您首先需要的是一个algorithm,即产生最终结果的一系列动作,在您的情况下 - 每个面额的硬币数量。dynamic programming大约有 16 种常用算法,你最可能需要解决这个问题的一种minimal是加起来 x 的数量,那么greedy algorithm应该可以解决问题。当您至少在脑海中掌握了算法时,那么考虑您将需要哪些数据类型会容易得多。

我不建议你处理一两天内无法解决的算法问题,因为这有点令人沮丧,至少对我来说是这样,除非那是作为家庭作业或其他东西。

于 2013-08-09T20:53:28.900 回答
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 调用添加一个检查以确保正确的数字输入,但这是您要解决问题的基本思路。

于 2013-08-10T07:41:39.047 回答