procedure TForm1.Button1Click(Sender: TObject);
  var  tBase:double; //Extended;
begin
  tbase:=4925.775; //这里是每个人工资所得税基数,几年来就上个月给财务审核出这个数计算有错
  edit2.Text:=formatFloat('0.00',4925.775);  // =4925.78
  edit3.Text:=formatFloat('0.00',tBase);  // =4925.77
  //后面导致扣税算成了 430.15 (实际应该是430.16)
end;
在工资系统税率计算中发现以上问题,并不是每个浮点数都有这样的计算问题(随便找了几个数也只发现这个4925.775有问题). 把变量声明改成: var tBase:Extended; 后,计算结果都为4925.78,这样虽然可以了,但我担心这样又会造成其他某些未知的浮点数计算时也会造成上述的问题.请对这方面有研究的兄弟谈谈该怎样处理?

解决方案 »

  1.   

    看到Lz用了formatfloat,他的参数要使用extend类型才会相对精确一些,不要直接传入小数,因为会有一个系统的默认转换在里面,先声明一个extend变量保存小数,然后把变量传进去
      

  2.   

    关于金额的,Delphi有个Currency类型,就是将整数/1000而得,建议你用用。
    用到浮点类型时,要注意到对于任何非二进位分式的数值,浮点数都无法精确表示。如 0.5是 1/2 ,0.3125是5/16,都可以精确保存,而 0.2 是 1/5,0.3是3/10都只能是近似值,所以建议用Currency。
      

  3.   

    不光delphi C C++一样有这样的浮点数问题。
      

  4.   

    应该用Currency类型,再用CurrToStr()转成字符串。
      

  5.   

    浮点数在计算机中的存储方式决定了是可能存在精度损失的,具体可以参考IEEE 754标准。
    但是lz用double存储4925.775这个值,肯定不至于损失精度。可能和FormatFloat的实现方式有关,FormatFloat的实现是用汇编的,看不懂,不好说。可以试试用RoundTo再用FloatToStr替代FormatFloat试试。另外如果确定小数点位数不会超出4位,建议用Currency。他是定点存储的。不会丢失精度。Extended只不多把浮点数存储的位数加大为10个字节。但是仍有可能丢失精度的。