MQL5-真实型(双精度型,浮点型)

本文探讨了MQL5语言中浮点数的表示方法及其精度限制,包括单精度(float)与双精度(double)的区别,并提供了如何正确比较浮点数的具体示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

真实型(双精度型,浮点型)

真实型(或浮点型)以小数部分为代表值,在MQL5语言里,浮点型数据有两种类型,在内存中实型数据的表示方法由 IEEE 754水平规定,它并不依赖平台、操作系统和程序语言。

类型字节大小最小正值最大值C++类似物
float41.175494351e-383.402823466e+38float
double82.2250738585072014e-3081.7976931348623158e+308double

双精度名称是为了表示这些浮点型数据的双倍准确率,在大多数情况下,双精度型是最方便的,浮点型数据的精密度限制是不够的,原因就在于浮点型数据还要节约内存(这就是真实型 数据庞大的重要性)。
浮点型数据由整数部分、小数点(.)和小数部分组成,其中整数部分和小数部分为一系列十进制数字。

示例:

double a=12.111;   
double b=-956.1007;   
float  c =0.0001;   
float  d =16; 

有更科学的方法输入实常数,通常这些方法比传统方法更简洁。

示例:

 double c1=1.12123515e-25;   
 double c2=0.000000000000000000000000112123515; // 小数点后有24个零 

 Print("1. c1 =",DoubleToString(c1,16));    
 // 结果: 1. c1 = 0.0000000000000000    

 Print("2. c1 =",DoubleToString(c1,-16));    
 // 结果: 2. c1 = 1.1212351499999999e-025 

 Print("3. c2 =",DoubleToString(c2,-16));    
 // 结果: 3. c2 = 1.1212351499999999e-025 

在二进制系统中,实型数据以限制精确度来存储,而常用作十进制计数法。这就是在十进制系统中,许多被取代的数字在二进制系统中被输出为无数小数点的原因。
例如,0.3和0.7的小数部分被取代,而0.25却被精确保留,因为它的有效数字是两位。
就这一点而言,不要实际地区对比两个真实数据,因为对比是不精确的。

示例:

void OnStart()  
{ 
//--
 double three=3.0;   
 double x,y,z;    
 x=1/three;    
 y=4/three;    
 z=5/three;    
 if(x+y==z) Print("1/3 + 4/3 == 5/3");    
 else Print("1/3 + 4/3 != 5/3");  
 // 结果: 1/3 + 4/3 != 5/3  
  } 

如果你仍需要对比两个真实型数据,有两种方法,第一种,在同样的小数位对比他们之间的不同。

示例:

bool EqualDoubles(double d1,double d2,double epsilon)   
{   if(epsilon<0) epsilon=-epsilon;  
//--    
if(d1-d2>epsilon) return false;    
if(d1-d2<-epsilon) return false;  
//--    
return true;   
}  
void OnStart()   
{    
double d_val=0.7;    
float  f_val=0.7;    
if(EqualDoubles(d_val,f_val,0.000000000000001)) Print(d_val," equals ",f_val);    
else Print("Different: d_val = ",DoubleToString(d_val,16),               
"  f_val = ",DoubleToString(f_val,16));  
// 结果: 不同: d_val= 0.7000000000000000   f_val= 0.6999999880790710   
} 

上例中第五位比DBL_EPSILON多,值是2.2204460492503131e-016,与浮点型数据相一致的是 FLT_EPSILON = 1.192092896e-07。这些值有如下意义:满足条件的最低值 1.0 + DBL_EPSILON! = 1.0(大量的浮点型数值 1.0 + FLT_EPSILON! = 1.0)。

第二种方法通过0将两种真实型数据进行了标准对比,它是无意义的,因为任何标准化操作都能给出非标准的结果。

示例:

bool CompareDoubles(double number1,double number2)   
{    
  if(NormalizeDouble(number1-number2,8)==0) return(true);    
  else return(false);   
  }  
  void OnStart()   
  {    
  double d_val=0.3;    
  float  f_val=0.3;
 if(CompareDoubles(d_val,f_val)) Print(d_val," equals ",f_val);    
 else Print("Different: d_val = ",DoubleToString(d_val,16),               
 "  f_val = ",DoubleToString(f_val,16));  
 // 结果: 不同: d_val= 0.3000000000000000   f_val= 0.3000000119209290 
}

一些数字协同处理器的操作能够导致无效的真实型数字,不能运用到数字操作和对比中,因为用无效真实型数据的操作结果是不能定义的。例如,当想要计算2的反正弦,结果可能无穷负。

示例:

 double abnormal = MathArcsin(2.0);    
 Print("MathArcsin(2.0) =",abnormal);  
 // 结果:  MathArcsin(2.0) = -1.#IND 

除了负无穷大也还有正无穷大和NaN(不是数字),确定数字是否是无效的,可以运用 MathIsValidNumber()。功能,根据IEEE标准,可以用专用机描述。例如,双精度型正无穷代表小的 0x7FF0 0000 0000 0000。

示例:

struct str1  
{   
double d;  
}; 
struct str2  
{   
long l;  
};
//--- 开始    
str1 s1;   
str2 s2; 
//--   
s1.d=MathArcsin(2.0);        // 获得无效数据 1.#IND   
s2=s1;   
printf("1.  %f %I64X",s1.d,s2.l); 
//--   
s2.l=0xFFFF000000000000;     // 无效数据 1.#QNAN   
s1=s2;   
printf("2.  %f %I64X",s1.d,s2.l); 
//--   
s2.l=0x7FF7000000000000;     // 最大 nonnumber SNaN   
s1=s2;   
printf("3.   %f %I64X",s1.d,s2.l); 
//--   
s2.l=0x7FF8000000000000;     // 最小 nonnumber QNaN   
s1=s2;   
printf("4.   %f %I64X",s1.d,s2.l); 
//--
 s2.l=0x7FFF000000000000;     // 最大 nonnumber QNaN   
printf("5.   %f %I64X",s1.d,s2.l); 
//--   
s2.l=0x7FF0000000000000;     // 正无穷大 1.#INF 和最小 nnonnumber SNaN   
s1=s2;   
printf("6.   %f %I64X",s1.d,s2.l); 
//--   
s2.l=0xFFF0000000000000;     // 负无穷大 1.#INF   
s1=s2;   
printf("7.  %f %I64X",s1.d,s2.l); 
//--   
s2.l=0x8000000000000000;     // 负零 0.0   
s1=s2;   
printf("8.  %f %I64X",s1.d,s2.l); 
//--   
s2.l=0x3FE0000000000000;     // 0.5   
s1=s2;   
printf("9.   %f %I64X",s1.d,s2.l); 
//--   
s2.l=0x3FF0000000000000;     // 1.0   
s1=s2;   
printf("10.  %f %I64X",s1.d,s2.l); 
//--   
s2.l=0x7FEFFFFFFFFFFFFF;     // 最大的规格化数字 (MAX_DBL)   
s1=s2;   
printf("11.  %.16e %I64X",s1.d,s2.l); 
//--   
s2.l=0x0010000000000000;     // 最小的正规格化 (MIN_DBL)   
s1=s2;   
printf("12.  %.16e %.16I64X",s1.d,s2.l); 
//--   
s1.d=0.7;                    // 显示数字0.7-无限循环部分   
s2=s1;   
printf("13.  %.16e %.16I64X",s1.d,s2.l); 
/* 
1.  -1.#IND00 FFF8000000000000 
2.  -1.#QNAN0 FFFF000000000000 
3.   1.#SNAN0 7FF7000000000000 
4.   1.#QNAN0 7FF8000000000000 
5.   1.#QNAN0 7FFF000000000000 
6.   1.#INF00 7FF0000000000000 
7.  -1.#INF00 FFF0000000000000 
8.  -0.000000 8000000000000000 
9.   0.500000 3FE0000000000000  
10.  1.000000 3FF0000000000000 
11.  1.7976931348623157e+308 7FEFFFFFFFFFFFFF 
12.  2.2250738585072014e-308 0010000000000000 
13.  6.9999999999999996e-001 3FE6666666666666 
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值