捐赠 | 广告 | 注册 | 发布 | 上传 | 关于我们    
  沪ICP备05001939号 DELPHI盒子 | 盒子论坛 | 盒子文章 | 盒子问答悬赏 | 最新更新 | 论坛检索 | 下载中心 | 高级搜索    
  精品专区 | 繁體中文 | 奖励公告栏 | 直通车账号登陆 | 关闭GOOGLE广告 | 临时留言    
 
广告
评论:拼凑组合发票的专用小程序
abclikeabc 36905 2009/3/10 18:19:46
  我记得以前做过一个排考场系统,要求与这个应该类似。因为这个算法可以这样:先采用与要凑的数字最接近的最大面额的票,然后将要凑的面额减去已凑好的数,于是要凑的值就会逐渐递减了。这个算法的好处是出结果非常快,缺点是有时人工可以凑整,计算出来的却可能+1了。可以试一下。
  临时想到哪写到哪了,语言可以不太可理解,望大家原谅。
lao1945 36901 2009/3/8 21:56:09
哪位介绍下咋更新上传的程序啊?我改了些bug,但不知道怎样能替换掉原来的?
lao1945 36891 2009/3/5 18:06:38
看了半天,终于发现了上边的几个小字,知道了您这段是干啥的了。。。
huhuc 36890 2009/3/5 17:52:37
我也来凑个热闹……
====分币凑整
function GetSumCB(sl:TStringList;target,error:Double):TStringlist;
var
  t: TStringlist;
  procedure GetAdd(tal:Double;R,Left:TStringlist);
  var
    i,cnt:Integer;
    value:Double;
    s,sA:string;
    nR,nLeft:TStringlist;
  begin
    value:=StrToFloat(Left.Names[Left.Count-1]);
    cnt:=StrToInt(Left.ValueFromIndex[Left.Count-1]);
    left.Delete(Left.Count-1);
    tal:=tal-value;
    for i:=0 to cnt do
    begin
      tal:=tal+value;
      if tal>target+error then exit;
      if i>0 then
      begin
        s:=FloatToStr(value)+'*'+IntToStr(i);
        R.Add(s);
        if Abs(tal-target)<=error then
        begin
          if tal=target then          
          sA:='[P]' else sA:='[Dlt='+Format('%.2f', [tal-target])+']';
          Result.Add('Method '+IntToStr(Result.Count+1)+sA+':'#13#10+R.Text);
        end;
      end;
      if left.Count>0 then
      begin
        nR:=TStringlist.Create;
        nLeft:=TStringlist.Create;
        nR.Assign(R);
        nLeft.Assign(Left);
        GetAdd(tal,nR,nLeft);
        nR.Free;
        nLeft.Free;
      end;
      if i>0 then R.Delete(R.Count-1);
    end;
  end;
begin
  Result:=TStringlist.Create;
  t:= TStringlist.Create;
  GetAdd(0,t,sl);
  t.Free;
  if Result.Count=0 then
    Result.Add('None') else Result.Add('Total '+IntToStr(Result.Count));
end;
procedure TForm1.btn1Click(Sender:TObject);
var
  s:TStringList;
begin
  s:=Tstringlist.Create;
  s.Add('3.1=9');
  s.Add('12.7=2');
  s.Add('5=5');
  MessageDlg(GetSumCB(s,68.3,1).Text,mtWarning, [mbOK],0);
end;
lao1945 36878 2009/3/4 11:58:00
sophialung算法的bug确认:
刚重新确认了一下,发现bug是在只用某一张就能满足条件时出现的问题。
如:输入一张1000的,然后输入10、20、30,目标设定为70,就得不到结果(但最接近值可以得到结果)
lao1945 36877 2009/3/4 11:21:10
另外,改过的代码,在找最接近的时候,往往结果跟选项1是一样的,而不是最接近的值?
lao1945 36875 2009/3/4 10:55:45
非常感谢!
超过<1即可,是指差额在1以内就可以了,本来是为了提高运算速度的(符合条件就可以跳出了),现在用不着了,呵呵。

刚试验中发现了一个小bug:当所有的面值都超过目标时,得不出结果。。。。
当然,这在实际中是用不着的一种情况。。。
sophialung 36873 2009/3/4 9:02:37
金額排序可以取消掉...沒有實際作用..排序只為Debug時習慣從小到大查看.在這個程式中不會加速運算..假300張票據在我的電腦使用排序 總時間會多加0.1秒...
racqs323 36872 2009/3/4 0:38:46
sophialung 算法的优势在于先对金额进行排序
sophialung 36870 2009/3/3 21:27:14
超過<1即可
這個選項不太明白實際意思..看原來代碼像是差額只能在0至1之間
所以有可能票據能滿額度,但差額不符
sophialung 36869 2009/3/3 21:22:25
//改進運算速度...原有使用power做循環好像不太科學 
//算法改進後,可取消32張發票運算的限制
procedure TForm1.Button2Click(Sender: TObject); //運算過程
var
  i, x, y, K: longint;
  j, z: integer;
  tmp, smallest: double;
  gengxiao: boolean;
  vDT: TDateTime;
  DataList: array of array of Double;
  vSUM_MY, vOLD_MY, vDST_MY: double;  
  procedure DataSort;
  var
    I, J: Integer;
    T, K: double;
  begin
    for I := High(DataList) downto Low(DataList) do
      for J := Low(DataList) to High(DataList) - 1 do
        if DataList[J, 1] > DataList[J + 1, 1] then
        begin
          K := DataList[J, 0];
          T := DataList[J, 1];
          DataList[J, 1] := DataList[J + 1, 1];
          DataList[J, 0] := DataList[J + 1, 0];
          DataList[J + 1, 1] := T;
          DataList[J + 1, 0] := K;
        end;
  end;
begin
  vDT := Now();

  RzStatusBar2.Visible := true;
  RzStatusBar1.Visible := false;
  SetLength(DataList, ValueListEditor1.RowCount - 1);

  for I := Low(DataList) to High(DataList) do
  begin
    SetLength(DataList[I], 4);
  end;
  for J := 1 to ValueListEditor1.RowCount - 1 do
  begin
    DataList[J - 1, 0] := J;
    DataList[J - 1, 1] := strtofloat(ValueListEditor1.Cells[0, j]);
  end;
  DataSort;

  vOLD_MY := cxCurrencyEdit1.Value * 2;
  for I := High(DataList) downto Low(DataList) do
  begin
    vDST_MY := cxCurrencyEdit1.Value;

    if DataList[I, 1] > vDST_MY then Continue;

    for J := I - 1 downto Low(DataList) do
    begin
      for k := Low(DataList) to High(DataList) do
        DataList[k, 2] := 0;
      DataList[I, 2] := 1;
      vSUM_MY := 0;
      vDST_MY := cxCurrencyEdit1.Value;
      vDST_MY := vDST_MY - DataList[I, 1];
      vSUM_MY := DataList[I, 1];
      for K := J downto Low(DataList) do
      begin
        vDST_MY := vDST_MY - DataList[K, 1];
        vSUM_MY := vSUM_MY + DataList[K, 1];
        DataList[K, 2] := 1;
        if vDST_MY <= 0 then Break;
      end;
      if (vOLD_MY - cxCurrencyEdit1.Value > vSUM_MY - cxCurrencyEdit1.Value) and (vSUM_MY - cxCurrencyEdit1.Value >= 0) and RadioButton1.Checked then
      begin
        for K := Low(DataList) to High(DataList) do
          DataList[K, 3] := DataList[K, 2];
        vOLD_MY := vSUM_MY;
      end;
      if (ABS(vOLD_MY - cxCurrencyEdit1.Value) > ABS(vSUM_MY - cxCurrencyEdit1.Value)) and RadioButton2.Checked then
      begin
        for K := Low(DataList) to High(DataList) do
          DataList[K, 3] := DataList[K, 2];
        vOLD_MY := vSUM_MY;
      end;
      if (vOLD_MY - cxCurrencyEdit1.Value > vSUM_MY - cxCurrencyEdit1.Value) and (vSUM_MY - cxCurrencyEdit1.Value >= 0)
        and (vSUM_MY - cxCurrencyEdit1.Value < 1) and RadioButton3.Checked then
      begin
        for K := Low(DataList) to High(DataList) do
          DataList[K, 3] := DataList[K, 2];
        vOLD_MY := vSUM_MY;
      end;
    end;

  end;

  for I := Low(DataList) to High(DataList) do
    ValueListEditor1.Cells[1, Trunc(DataList[I, 0])] := InttoStr(Trunc(DataList[I, 3]));

  if vOLD_MY <> cxCurrencyEdit1.Value * 2 then
  begin
    if vOLD_MY - cxCurrencyEdit1.Value > 0 then
      RzStatusPane3.Caption := '超額:' + floattostr(Abs(vOLD_MY - cxCurrencyEdit1.Value))
    else
      RzStatusPane3.Caption := '尚缺:' + floattostr(Abs(vOLD_MY - cxCurrencyEdit1.Value));
    RzStatusPane2.Caption := '當前:' + floattostr(vOLD_MY);
  end else begin
    RzStatusPane3.Caption := '';
    RzStatusPane2.Caption := '';
  end;
  RzStatusBar2.Visible := false;
  RzStatusBar1.Visible := true;

  Self.Caption := FloattoStr((Now() - vDT) * 24 * 60 * 60);
end;
zh2000 36868 2009/3/3 17:36:05
汗...竟然不知道做什么用的...那位说说实际是什么用的.....
luweilove 36866 2009/3/3 15:00:06
呵呵,以前我天天都要计算!
第一页 上一页 下一页 最后页 有 13 条纪录 共1页 1 - 13
 用户名:
 密 码:
自动登陆(30天有效)
 
  DELPHI盒子版权所有 1999-2023 V4.01 粤ICP备10103342号-1 更新RSS列表