数字与字符串的相互转换

数字与字符串的相互转换可以使用 显式类型强制转换 运算符完成。例如,对于 doublestring 类型,可能如下所示:

double number = (double)text;
string text = (string)number;

字符串可转换为其它数值类型,诸如 floatlongint 等等。

请注意,强制转换为实数类型 (float) 可实现更少的有效数位,这在某些应用中可能有优势,因为实数类型更紧凑,表示形式更易读。

严格来讲,这种类型强制转换并非强制性的,因为即使没有显式强制转换运算符,编译器也会隐式生成类型强制转换。但是在这种情况下将会出现编译器警告,因此,建议始终进行显示类型强制转换。

MQL5 API 还提供了其他一些有用的函数,将在下文中介绍。说明后面附带一般示例。

double StringToDouble(string text)

StringToDouble 函数可将字符串转换为 double 数字。

它是对到 (double) 的类型强制转换的完整模拟。其实用目的实际上仅仅是保持与旧版源代码的向后兼容性。首选方法是类型强制转换,因为它更紧凑,并在语言句法内实现。

根据转换过程,字符串应包含满足数值类型(包括 浮点数整数)字面量写入规则的一系列字符。尤其是字符串能以 '+' 号或 '-' 号开头,后面是数字,并且后面还可以一系列数字。

实数可包含单点字符 '.',按以下格式分隔小数部分和可选的指数:字符 'e' 或 'E',后面是表示指数的一系列数字(其前面也可添加 '+' 或 '-')。

对于整数,支持十六进制计数法,即 "0x" 前缀后面不仅可以跟十进制数字,而且可以跟 'A'、'B'、'C'、'D'、'E'、'F'(在任何位置)。

当字符串中碰到任何非预期字符(诸如字母、标点符号、第二句号或中间空格)时,转换终止。在此情况下,若在该位置前有允许的字符,它们被解释为数字,反之,结果将为 0。

初始空字符(空格、制表符、换行符)被跳过,不影响转换。如果后面是满足规则的数字及其它字符,则该数字将被正确接收。

下表提供了带有说明的一些有效转换示例。

字符串

双精度浮点数

结果

"123.45"

123.45

一个小数点

"\t 123"

123.0

开始部分的空白字符被忽略

"-12345"

-12345.0

有符号数

"123e-5"

0.00123

带指数的科学计数法

"0x12345"

74565.0

十六进制记数法

下表列出了不正确转换示例。

字符串

双精度浮点数

结果

"x12345"

0.0

以无法解析的字符(字母)开始

"123x45"

123.0

123 后面的字母中断了转换

" 12 3"

12.0

12 后面的空格中断了转换

"123.4.5"

123.4

123.4 后面的第二个小数点中断了转换

"1,234.50"

1.0

1 后面的逗号中断了转换

"-+12345"

0.0

太多符号(两个)

string DoubleToString(double number, int digits = 8)

DoubleToString 函数将数字转换为具有指定精度的字符串(位数从 -16 到 16)。

它的功能类似于将数字强制转换为 (string),但允许你使用第二个参数选择生成的字符串的数字精度。

应用到 double 的运算符 (string) 显示 16 个有效数位(总计,包括尾数和小数部分在内)。函数无法实现与此完全等效的结果。

如果 digits 参数大于或等于 0,则其表示小数位数。在此情况下,小数点前面的字符数由数字本身(数字大小)确定,并且如果尾数中的总字符数以及 digits 中指示的总字符数大于 16,则最不重要的数位将包含“垃圾”(由于 实数 存储的方式而导致)。16 个字符表示 double 类型的平均最大精度,也就是将 digits 设为 16(最大)将仅提供低于 10 的准确值表示。

如果 digits 参数小于 0,则其指定有效数位数,该数字将以带指数的科学计数法输出。就精度(而不是记录格式)而言,在函数中设置 digits=-16 将生成接近强制转换 (string) 的结果。

该函数通常用于统一数据集的格式设置(包括某个表格的列右对齐),使得值具有相同的小数精度(例如,金融工具价格或手数的小数位数)。

请注意,数学计算过程中可能发生错误,导致结果不是一个有效数字,尽管该数字的类型为 double(或 float)。例如,一个变量可能包含计算负数的平方根的结果。
 
此类值称为“非数字” (NaN) 值,并在强制转换为 (string) 时显示为简短错误类型提示,如 -nan(ind)(ind - 未定义)、nan(inf)(inf - 无穷)。使用 DoubleToString 函数时,会得到一个不合理的大数字。
 
尤其重要的是,所有具有 NaN 的后续计算也将给出 NaN。要检查此类值,可使用 MathIsValidNumber 函数。

 

long StringToInteger(string text)

该函数将字符串转换为 long 类型的数字。请注意,结果类型肯定为 long,而不是 int(不论名称如何)或 ulong

一种替代方法是使用运算符 (long) 进行类型强制转换。此外,你选择的任何其它整数类型均可用于强制转换:(int)(uint)(ulong) 等等。

转换规则类似于 double 类型,但不包括点字符以及来自允许字符的指数。

string IntegerToString(long number, int length = 0, ushort filling = ' ')

函数 IntegerToStringlong 类型的整数转换为指定长度的字符串。如果数字表示少于一个字符,则其左填补一个字符 filling(默认填补一个空格)。否则,数字完整无限制显示。调用具有默认参数的函数等效于强制转换为 (string)

当然,较小的整数类型(如 intshort)可以由函数成功处理。

使用所有上述函数的示例在脚本 ConversionNumbers.mq5 中提供。

void OnStart()
{
   const string text = "123.4567890123456789";
   const string message = "-123e-5 buckazoid";
   const double number = 123.4567890123456789;
   const double exponent = 1.234567890123456789e-5;
   
   // type casting
   Print((double)text);    // 123.4567890123457
   Print((double)message); // -0.00123
   Print((string)number);  // 123.4567890123457
   Print((string)exponent);// 1.234567890123457e-05
   Print((long)text);      // 123
   Print((long)message);   // -123
   
   // converting with functions
   Print(StringToDouble(text)); // 123.4567890123457
   Print(StringToDouble(message)); // -0.00123
   
   // by default, 8 decimal digits
   Print(DoubleToString(number)); // 123.45678901
   
   // custom precision
   Print(DoubleToString(number5));  // 123.45679
   Print(DoubleToString(number, -5)); // 1.23457e+02
   Print(DoubleToString(number, -16));// 1.2345678901234568e+02
   Print(DoubleToString(number16)); // 123.4567890123456807
   // last 2 digits are not accurate!
   Print(MathSqrt(-1.0));                 // -nan(ind)
   Print(DoubleToString(MathSqrt(-1.0))); // 9223372129088496176.54775808
   
   Print(StringToInteger(text));      // 123
   Print(StringToInteger(message));   // -123
   
   Print(IntegerToString(INT_MAX));         // '2147483647'
   Print(IntegerToString(INT_MAX5));      // '2147483647'
   Print(IntegerToString(INT_MAX16));     // '      2147483647'
   Print(IntegerToString(INT_MAX16, '0'));// '0000002147483647'
}