浮点运算,急(50分)

  • 主题发起人 主题发起人 wghua
  • 开始时间 开始时间
W

wghua

Unregistered / Unconfirmed
GUEST, unregistred user!
我在进行浮点运算如下:
FieldByName('WillPay').AsCurrency :=
FieldByName('BasePay').AsCurrency
+ FieldByName('LivePay').AsCurrency + FieldByName('AreaDiff').AsCurrency
+ FieldByName('JOBFEE').AsCurrency + FieldByName('BOUNTY').AsCurrency
+ FieldByName('TEMPPAY').AsCurrency + FieldByName('OTHERSPAY').AsCurrency;

X := FieldByName('WillPay').AsCurrency;
调试看到的结果X= 0.115,事实上也应等于0.115,
但用Trunc(X*(IntPower(10,i)) + 0.5)/IntPower(10,i))后结果是0。11,而不是0。12,
为什么?

用FloatToStr(FieldByName('WillPay').AsFloat)返回的值是0.114999999999998;
为什么?

我是想进行四舍五入操作,请问有什么办法解结?

 
Trunc对于Extended型是对的,对其他的浮点都存在这个问题.
 
四舍五入应该用 round 啊,怎么用 trunc 了?

round (X*(IntPower(10,i)) + 0.5)/IntPower(10,i)) 试试,

>> 用FloatToStr(FieldByName('WillPay').AsFloat)返回的值是0.114999999999998;

原因是系统在浮点数运算的时候产生的误差,这是不可避免的,
所以不要用 浮点数 在程序中作 = 条件测试,
 
谢谢各位快速响应.
加了0.5当然用Trunc(),我知道是机器误差,想问下有无办法解结?
四舍五入用Trunc(X*(IntPower(10,i)) + 0.5)/IntPower(10,i))应是可以,
但是传进去的X有误差就不准了(本来是0.115,变成了0.114999999998),
用Trunc(X*(IntPower(10,i)) + 0.5)/IntPower(10,i))也就出错了.

 
更正:
错:X := FieldByName('WillPay').AsCurrency
正确:
(FieldByName('WillPay').AsCurrency := 1202。30)
X := ((FieldByName('WillPay').AsCurrency)-1200)*0.05 (X 在调试中看到是0.115,
但用FloatToStr(X)后却变成了0。114999999999998)
I := Trunc(X*(IntPower(10,i)) + 0.5)/IntPower(10,i))后,
I等于0.11,这与结果应为0.12相伪。
这应是X值有了误差,这么简单的算术运算,怎么保证它没有误差?

另,FloatToStrF(X,。。。)的参数不是很明白?请指教。
 
将bde的enable bcd 设为true就可以
 
我也碰到过运算碰到过类似 0。23999999 的结果,也不知该怎么解决?
 
我也碰到过运算碰到过类似 0。23999999 的结果,也不知该怎么解决?
 
用floattostrf比较好,取定点ffFixed,规定保留位数
 
将bde的enable bcd 设为true就可以


 
format('%0.2f',[x])将把x保留到小数点后2位数。(四舍五入而不是四舍六入五成双)
 
所有中间变量都用Extended类型可减小误差。
procedure TForm1.Button1Click(Sender: TObject);
const
FieldName='艰苦边远津贴';
var
VReal48:Real48;
VSingle:Single;
VDouble:Double;
VExtended:Extended;
VCurrency:Currency;
begin
Table1.Open;
Table1.Edit;
Table1.FieldByName(FieldName).AsCurrency:=1202.30;
Table1.Post;
Vreal48:=((Table1.FieldByName(FieldName).AsCurrency)-1200)*0.05;
Memo1.lines.Add('Real48:='+FloatToStr(VReal48));
VSingle:=((Table1.FieldByName(FieldName).AsCurrency)-1200)*0.05;
Memo1.lines.Add('Single:='+FloatToStr(VSingle));
VDouble:=((Table1.FieldByName(FieldName).AsCurrency)-1200)*0.05;
Memo1.lines.Add('Double:='+FloatToStr(VDouble));
VExtended:=((Table1.FieldByName(FieldName).AsCurrency)-1200)*0.05;
Memo1.lines.Add('Extended:='+FloatToStr(VExtended));
VCurrency:=((Table1.FieldByName(FieldName).AsCurrency)-1200)*0.05;
Memo1.lines.Add('Currency:='+FloatToStr(VCurrency));
Table1.Close;
end;
结果(Memo1.lines):
Real48:=0.115000000000009
Single:=0.115000002086163
Double:=0.115
Extended:=0.115
Currency:=0.115

(Delphi 5 , Oracle 8.0.5)
 
尽量用double类型,而少用float类型

字符串-->浮点数
AnsiString Str = "11.12";
double Num = StrToFloat(Str);

浮点数-->字符串
double Num = 11.12;
AnsiString Str = FloatToStr(Num);

浮点数之间的运算可用下列方法控制:
double a1 = 11.12;
double a2 = AnsiString::FormatFloat("0.00",a1).ToDouble();
 
多人接受答案了。
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
I
回复
0
查看
763
import
I
后退
顶部