function TfrmRPDesigner.FloatToCnMoney(Num: Double): string;
const
  mnUnit:String='分角元';
  hzUnit:String='拾佰仟万拾佰仟亿拾佰仟万拾佰仟';
  hzNum:String='零壹贰叁肆伍陆柒捌玖';
var
  szChMoney,szNum:String;
  iLen, iNum, iAddZero,i:integer;
  function DRound(Value:double;cnt:byte):double;
  var
    fTmp:double;
    nTmp:double;
    k:int64;
  begin
    Result:=Value;
    if cnt>18 then exit;
    nTmp:=Power(10.0,cnt);
    fTmp:=0.5;
    fTmp:=fTmp/nTmp;
    Result:=fTmp+Result;
    Result:=Result*nTmp;
    k:=0;
    asm
      fld qword ptr Result
      //__ftol   begin
      push ebp
      mov ebp,esp
      LEA ESP,k
      wait
      fstcw word ptr [ebp-$04]
      wait
      mov al,[ebp-$03]
      or [ebp-$04],$00000c01
      fldcw word ptr [ebp-$04]
      fistp qword ptr [ebp-$0c]
      mov [ebp-$03],al
      fldcw word ptr [ebp-$04]
      mov eax ,[ebp-$0c]
      mov edx,[ebp-$08]
      mov esp,ebp
      pop ebp
      //__ftol   end
      push esp
      lea esp,k
      mov [esp],eax
      add esp,4
      mov [esp],edx
      mov esp,ebp
      pop esp
      fild qword ptr k
      fstp qword ptr Result
      fld qword ptr nTmp
      fdivr qword ptr Result
      fstp qword ptr Result
    end;
  end;
begin
  iAddZero:=0;
  szNum:=FormatFloat('0', DRound(Num,2)*100.0); //这样可能会有数字误差,double只有15位有效数字,这里只有13
  Result:='';
  iLen:=Length(szNum);
  if Pos('E',UpperCase(szNum))>0 then exit;
  if (iLen>18) or (iLen=0) or (Num<0) then exit; //数据错误返回  for i:=1 to iLen do
  begin
    iNum:=StrToInt(copy(szNum,i,1));
    if iNum=0 then
    begin
      if (((iLen-i-2) mod 4)=0) and ((iLen-i-3)>0) and (((iLen-i)>=8) or (iAddZero<3)) then
        szChMoney:=copy(szChMoney+hzUnit,((iLen-i-3) mod 8)+1,1);
      inc(iAddZero);
    end
    else
    begin
      if ((iAddZero>0) and ((iLen-i)>=2)) and (((iLen-i-1) mod 4)<>0) then
      szChMoney:=szChMoney+copy(hzNum,1,1);
      szChMoney:=szChMoney+copy(hzNum,iNum+1,1);
      iAddZero:=0;
    end;
    if (iAddZero<1) or ((iLen-i)=2) then
    if (iLen-i)>=3 then
    begin
      szChMoney:=szChMoney+copy(hzUnit,((iLen-i-3) mod 8)+1,1);
    end
    else
    szChMoney:=szChMoney+copy(mnUnit,((iLen-i) mod 3)+1,1);
  end;
  if Trim(szChMoney)='' then
    szChMoney:='零元整'
  else
  if copy(szNum,Length(szNum),1)='0' then szChMoney:=szChMoney+'整';
  Result:=szChMoney;
end;----------------
以上的算法,万位为0的时候出错了,比如要转换101000就出错请大家帮帮我,谢谢大家!!!

解决方案 »

  1.   


    function TfrmRPDesigner.FloatToCnMoney(Num: Double): string;
    const
      mnUnit:String='分角元';
      hzUnit:String='拾佰仟万拾佰仟亿拾佰仟万拾佰仟';
      hzNum:String='零壹贰叁肆伍陆柒捌玖';
    var
      szChMoney,szNum:String;
      iLen, iNum, iAddZero,i:integer;
      function DRound(Value:double;cnt:byte):double;
      var
        fTmp:double;
        nTmp:double;
        k:int64;
      begin
        Result:=Value;
        if cnt>18 then exit;
        nTmp:=Power(10.0,cnt);
        fTmp:=0.5;
        fTmp:=fTmp/nTmp;
        Result:=fTmp+Result;
        Result:=Result*nTmp;
        k:=0;
        asm
          fld qword ptr Result
          //__ftol   begin
          push ebp
          mov ebp,esp
          LEA ESP,k
          wait
          fstcw word ptr [ebp-$04]
          wait
          mov al,[ebp-$03]
          or [ebp-$04],$00000c01
          fldcw word ptr [ebp-$04]
          fistp qword ptr [ebp-$0c]
          mov [ebp-$03],al
          fldcw word ptr [ebp-$04]
          mov eax ,[ebp-$0c]
          mov edx,[ebp-$08]
          mov esp,ebp
          pop ebp
          //__ftol   end
          push esp
          lea esp,k
          mov [esp],eax
          add esp,4
          mov [esp],edx
          mov esp,ebp
          pop esp
          fild qword ptr k
          fstp qword ptr Result
          fld qword ptr nTmp
          fdivr qword ptr Result
          fstp qword ptr Result
        end;
      end;
    begin
      iAddZero:=0;
      szNum:=FormatFloat('0', DRound(Num,2)*100.0); //这样可能会有数字误差,double只有15位有效数字,这里只有13
      Result:='';
      iLen:=Length(szNum);
      if Pos('E',UpperCase(szNum))>0 then exit;
      if (iLen>18) or (iLen=0) or (Num<0) then exit; //数据错误返回  for i:=1 to iLen do
      begin
        iNum:=StrToInt(copy(szNum,i,1));
        if iNum=0 then
        begin
          if (((iLen-i-2) mod 4)=0) and ((iLen-i-3)>0) and (((iLen-i)>=8) or (iAddZero<3)) then
            szChMoney:=copy(szChMoney+hzUnit,((iLen-i-3) mod 8)+1,1);
          inc(iAddZero);
        end
        else
        begin
          if ((iAddZero>0) and ((iLen-i)>=2)) and (((iLen-i-1) mod 4)<>0) then
          szChMoney:=szChMoney+copy(hzNum,1,1);
          szChMoney:=szChMoney+copy(hzNum,iNum+1,1);
          iAddZero:=0;
        end;
        if (iAddZero<1) or ((iLen-i)=2) then
        if (iLen-i)>=3 then
        begin
          szChMoney:=szChMoney+copy(hzUnit,((iLen-i-3) mod 8)+1,1);
        end
        else
        szChMoney:=szChMoney+copy(mnUnit,((iLen-i) mod 3)+1,1);
      end;
      if Trim(szChMoney)='' then
        szChMoney:='零元整'
      else
      if copy(szNum,Length(szNum),1)='0' then szChMoney:=szChMoney+'整';
      Result:=szChMoney;
    end;
    不好意思,这个是缩进的了
      

  2.   

    1. Dround可考虑直接用format函数替换。
    2. 调试可知首次问题出现在开头的下列语句。
    if iNum=0 then
        begin
          if (((iLen-i-2) mod 4)=0) and ((iLen-i-3)>0) and (((iLen-i)>=8) or (iAddZero<3)) then
            szChMoney:=copy(szChMoney+hzUnit,((iLen-i-3) mod 8)+1,1);
          inc(iAddZero);
        end
    3. 对于这种转换问题,个人倾向用递归方式解决。