读书人

Delphi Trunc函数精度的有关问题能解

发布时间: 2012-02-09 18:22:27 作者: rapoo

Delphi Trunc函数精度的问题,能解答送200分
var
a , b, c ,d : Double;
i : Integer;
begin
a := 0.3;
b := 0.3;
c := 300000;

d := a * b * c;
i := Trunc(d);//26999不是 27000
Memo1.Lines.Add( 'd := a * b * c; i := Trunc(d)= '+IntToStr(i));
i := Trunc(d * 10000);//269999999 不是 270000000
Memo1.Lines.Add( 'd := a * b * c; i := Trunc(d)= '+IntToStr(i));
end;

怎么才能让Trunc得到我想要的精度?
尝试在trunc前加一个很小的值

d := d+ 1e-11;
i := Trunc(d);
有效
d := d+ 1e-12;
i := Trunc(d);
则仍然有刚才的问题。

其他语言,例如c、c#尝试同样数值的乘法并取整没有这种问题。
浮点数精度上有问题但总觉得round有差异是可以理解,怎么在delphi中一个很正常的数取整也有问题呢?
---
c中测试浮点数表示值
union D
{
double f ;
struct
{
unsigned char x1 ;
unsigned char x2 ;
unsigned char x3 ;
unsigned char x4 ;
unsigned char x5 ;
unsigned char x6 ;
unsigned char x7 ;
unsigned char x8 ;
} ;
} u,v ;
double a = 0.3;
double b = 0.3;
double c = 300000;
u.f=a*b*c;
printf( "u.f=%30.20f\n ",u.f);
printf( "%2x %2x %2x %2x %2x %2x %2x %2x\n ",u.x8,u.x7,u.x6,u.x5,u.x4,u.x3,u.x2,u.x1) ;

u.f= 27000.00000000000000000000
40 da 5e 0 0 0 0 0

---
c#测试相关代码
double a = 0.3;
double b = 0.3;
double c = 300000;
double d = a * b * c;
this.textBox1.Text = Convert.ToInt32(Math.Truncate(d)).ToString();

能解答送200分

[解决办法]
请把 Double换成
Extended类型
[解决办法]
在计算机中浮点数的表达是近似值,a*b*c是近似=27000,而这里刚好得到的是26999.999999999996362,所以出现了Trunc(d)=26999的情况,为避免这种情况出现,
特别是在金融等的计算上面,往往需要限定d的精度,否则会出现这种微小的误差,而这误差累积起来,就会出现大的bug。a,b,c可以是double,但是结果不能用高精度的类型,设置为低精度的Single或者Currency类型可以很好的来避免。

读书人网 >.NET

热点推荐