English Русский Español Deutsch 日本語 Português
preview
掌握 MQL5:从入门到精通(第二部分)基本数据类型和变量的使用

掌握 MQL5:从入门到精通(第二部分)基本数据类型和变量的使用

MetaTrader 5示例 | 26 七月 2024, 09:46
962 0
Oleh Fedorov
Oleh Fedorov

概述

上一篇文章中,我们了解了 MQL5 程序员使用的主要程序(并得出了 MetaEditor IDE 非常适合初学者的结论)。此外,我们还快速了解了函数的概念,并创建了一个在系统日志中打印一条信息的简单脚本。这些信息可在终端窗口底部的 "专家" 选项卡中查看。

让我提醒大家,函数 是对行为的描述。

我们只使用了预定义的函数:OnStartPrint。至于第一个函数,我们使用内容来填充它。第二个显示我们所需的信息的函数是已经完成的,我们只需将参数传递给它。程序员可以创建自己所需的自定义函数,以解决特定任务。

每个函数都由非常基本的分步操作组成,这些步骤被称为语句。这些操作非常简单:比较两个数字、多次重复一段代码、将两个文本粘合在一起、调用另一个函数等。这样的操作不多。我们将在本文中讨论其中的一些语句。

一连串的语句构成了一种算法

算法由清晰易懂的指令组成,执行者(在本例中为计算机)根据指令执行某些操作,从而解决特定的、更全面的任务。由于同样的问题通常可以用多种不同的方法解决,因此算法的数量非常庞大。

有关交易的时候更是如此。进场交易、退出交易、打印相应日志和其他操作可以通过不同的方式实现。我们需要绝对清楚地向计算机解释,在特定情况下,您(或您的客户)到底想要什么。

我们可以说,更复杂的算法是由更简单的算法组成的,而每种算法都是由某些函数实现的,执行某些操作。这些操作是应用于数据的。这些数据可以是每秒多次到达的买卖报价或交易量。其他数据示例还包括屏幕上的点,您可以在这些点之间绘制直线或曲线。也可以是在执行交易时播放的声音。数据可以是文本,例如某个时间段的报价列表。可以有很多不同的例子。我希望这个想法是清楚的。

现在,我们要讨论的是,这些数据必须存储在某个地方。

今天,我们将讨论如何在 RAM 中存储数据。数据可以作为变量常量存储在内存中。

它们的差别是显而易见的:

  • 变量可以变化,即程序有权改写这些数据。
  • 常量在整个程序生命周期内保持恒定(不变),如果程序员试图覆盖其值,将返回编译错误。

除此之外,它们的含义绝对相似:这是 RAM 中存储数据而非处理器指令的特定区域。通常,人们会为这些内存区域提供有意义的名称,以便知道它们的用途。

编译器会移除这些名称,但如果您可以访问源代码(文本文件),您总是可以根据变量名理解变量的用途。当然,前提是描述正确。

常量在某些情况下可能没有名称。程序员只需写入需要处理的内容(例如,我们传递给 Print 函数的字符串)。这种没有名称的常量被称为字面常量

在本文中,我们将仔细研究基本数据类型、描述变量和常量的方法,以及程序员用来创建算法的基本语句。这反过来又能让你创建更多有用的程序,而不仅仅是 "Hello, World"。


测试文章中所有表达式的基本代码

在上一篇文章中,我们创建了一个简单的程序:在终端底部面板的"专家"选项卡中打印数据的脚本。就是这样:

//+------------------------------------------------------------------+
//|                                                   HelloWorld.mq5 |
//|                                       Oleg Fedorov (aka certain) |
//|                                   mailto:coder.fedorov@gmail.com |
//+------------------------------------------------------------------+
#property copyright "Oleg Fedorov (aka certain)"
#property link      "mailto:coder.fedorov@gmail.com"
#property version   "1.00"
//#property script_show_inputs

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---
  Print("Hello, MQL5 world!");
  }

//+------------------------------------------------------------------+

例 1. 最简单脚本的全文

今天,我们将使用这段代码:我们将在大括号内插入示例中的代码行来修改这段代码(除非示例说明中明确指出了插入的其他位置)。


字面符号

让我们看看如何打印数据。

我们将从字符串开始。

字符串文字用双引号<"> 括起来然而,并非所有字符都能以直观的方式显示。其中有些字符在语言中具有特殊含义(相同的引号),有些则完全不显示,例如换行符。

此类字符有一个特殊的约定:使用反斜杠书写:

Print(
    "Symbol <\"> can't be placed"
    " without (\\).\n  And we can carrying over the string now."
  );

例 2.使用反斜杠打印特殊字符

在例 2 中,描述输出字符串的引号用绿色突出显示,特殊字符用黄色突出显示。因此,"\n"表示换行。

字符串按字面输出示例

图1. 字符串字面输出示例

还请注意以下功能。在 MQL5 中,超长字符串可以在任意位置分割(通过将每个部分放在引号中)。无需添加任何其他操作来合并这些行。如果编译器遇到两个连续的字符串字面量(如示例中),它会自动将这两个字符串合并为一个大字符串,然后搜索其中的特殊字符。

完整的特殊字符表以及更详细的字符常量说明,请参见官方帮助

第二种最常用的类型是数字。

整数有统一的形式:

Print(5);

例 3.整数输出

小数也很容易输出。整数和小数部分之间的分隔符是点:

Print(5.5);

例4. 小数输出

对于非常大或非常小的数字,可以使用浮点符号(有时称为指数形式):

Print(5.5e3);
Print(5.5e-3);

例 5. 使用浮点字面量

使用所有这些数字形式的脚本结果如图 2 所示。

使用 Print 函数打印数字

图 2. Print 函数打印数字的结果

请注意在最后两行中函数是如何转换传递给它的数据的。这表明数据被识别为数字,并得到了正确处理。

有时,程序员需要处理十六进制数字。初学者很少需要这种类型,但有时它也很有用,例如在描述颜色时。十六进制数由数字(0...9)和/或字母(a...f)组成。

为了让程序理解这是十六进制文字,需要在数字开头添加 "0x"(0 和字母x)。

该表示法不区分大小写。

Print(0xAF35);

例6. 使用十六进制数

十六进制数字输出

图 3. 十六进制数字输出结果

脚本结果如图 3 所示。该数字已被转换(为普通整数),这意味着计算机完全按照需要来理解它。

MQL5 程序员经常需要使用日期。

如果要完整地标注日期和时间,请以大写字母"D"开头,然后加上单引号< ' >,必要时用圆点或斜线写出所需的日期,在空格后标注时间,用冒号分隔分钟和秒,再加上另一个单引号:

  Print(D'24/12/23');
  Print(D'24.12');
  Print(D'24.12.2023 7:55:34');

例 7.使用日期和时间

请注意,如果有第二行,我们会收到编译器警告,提示日期不完整。不过,文件将被编译,所有三行都将正常工作:

不完整的字面警告

图 4. 关于日期字面不完整的警告(MetaEditor)

脚本结果(日期的输出)

图 5. 日期输出脚本的结果(终端)

请注意,在编译第一行时,替换的是一天的开始时间,而在编译第二行时,替换的是编译的时间。既然格式转换正确,我们可以断定程序理解正确。

在任何字面量上,都可以执行给定数据类型允许的任何操作。

例如,您可以比较数字、执行算术运算并将数字作为参数传递给函数。

字符串可以添加(粘在一起),但不能相减。

让我们看看下面的例子:

Print( "This will be calculated: "+4+9 );
Print( "This will be calculated: "+(4+9) );

例 8.在书写表达式时使用括号。

编译器警告在字符串表达式中使用数字

图 6. 编译器警告在字符串表达式中使用数字

计算结果

图 7. 函数输出计算结果

在没有括号的地方,数字只是"粘"在文本上。当我们使用括号时,一切都计算正确。这是一个相当难以捉摸的错误,因此编译器会立即发出警告。有一些特定函数可以明确地将数字转换为字符串。但现在请记住:括号很重要


使用 #define 预处理器指令定义常量

如果不想在自己的代码中混淆,又想理解程序中使用数据的目的,就应该尽量为所有常量设置有意义的名称。为此,通常使用#define预处理器指令:
#define name value

例 9.#define 指令

让我提醒您,预处理器语言就像是 "语言中的语言",这种语言描述的是编译开始之前的操作。

通常,预处理器的目的是用其他代码片段替换某些代码片段。例如,第一次传递时的#define指令会指示编译器在整个代码中将"name" 替换为"value",然后才开始语法检查。

例如,我们可以这样写:

  #define MY_SUPER_CONSTANT 354
  Print(MY_SUPER_CONSTANT);

例 10.#define 指令

程序输出数值,而不是名称

图 8. 程序会输出常量的值,而不是名称

执行时,程序显示的正是数字 354,而不是名称。

注意,描述数字的文字后面没有分号。

使用预处理器指令声明常量时,不需要分号。

如果我们添加了分号,预处理器就会在 Print 括号内插入分号和数字,我们就会收到编译错误信息。

因此,请记住,我们命名一个常量,并在表达式中使用它的名称,而不是值

顺便说一句,当同一个常量在程序的不同地方被多次使用,或者几个常量的值相同时, 名称就非常有用了。如果常量的值发生变化,只需在一个地方(通常是在文档的开头,甚至是在一个单独的文件中)进行更改即可,而不必在多个地方进行搜索和更改。


变量的描述

请记住:如果预计内存中的数据会在工作过程中发生变化,请使用变量。

对变量的描述也非常简单,只需写下您想要存储的内容即可:

type variable_name;

例 11.变量声明模板

这条内容意味着编译器必须为数据分配一定量的内存。稍后我们将详细介绍类型和大小。

现在可以通过名称(variable_name) 访问这些数据。


标识符约定

变量名(通常称为标识符)以及您创建的任何名称必须

  • 要包含信息("chartNumber "比 "sss "更好)、
  • 由拉丁字母、数字和下划线 (_) 组成。 

名称不能

  • 以数字开头、
  • 保留字冲突、
  • 长于 63 个字符。

名称区分大小写。例如,myVariable 和 MyVariable 是两个不同的名称。(显然,强烈建议不要在同一个文件中同时使用这两个名称)。

如果不小心在程序文本的某个地方混淆了大小写,编译器就会给出错误信息:"Undeclared variable"(未声明的变量),这样你就可以很容易地修复它。但如果按照所有规则来描述这两个变量,但使用了只是大小写不同的相似名称,那就太容易混淆了。

其它方面,没有任何限制。如果你愿意,甚至可以用某个内置函数来命名你的变量(希望不要)。


赋值操作符

要将数据写入变量,请使用赋值操作。有时在声明时进行赋值,这种情况被视为初始化

// Initialization (at creation)
int counter = 0;
// Normal assignment
counter = 10;

例 12.简单赋值

int表示变量只能包含整数类型的数据。

本例中的符号"="表示赋值运算符在这种情况下,一个整数被写入名为 "counter"的单元格。

赋值前单元格中的所有数据都会丢失。

该变量中的数据可以在程序中的任何地方按名称使用,例如,可以将其作为参数传递给任何函数或在表达式中使用(本文稍后将举例说明)。


赋值操作 - 功能特点

赋值可以非常简单,如上一节所述。但如果您在表达式中使用此操作,下面的说明将帮助您更有效地使用它。

  • 赋值操作的优先级最低,因此从右向左执行。也就是说,右侧是一个表达式,左侧是一个写入数据的变量。首先,表达式为:
a = b + c;

例 13.赋值的优先级最低。

上面的表达式会先将 b 和 c 相加,然后将表达式的结果写入变量 a。

  • 根据前面的分析,可以在表达式中使用变量的值,然后将结果写入同一变量:
a = a — c;

    例 14.您可以在表达式中使用变量的前值

    • 在 MQL5 中,如果同一变量在左右两侧各出现一次(如上例),则可以通过将表达式符号移至操作的左侧来简化表达式:
    a -= c;

    例 15.赋值的简短用法

    这种简短的用法适用于任何二元(使用两个值,如和或乘)运算符:乘法、除法、移位等。不过要注意的是,这个表达式中的变量应该很容易分离出来。

    例如,对于表达式 a = a*(1+1/a),如果不打开括号,这一招就不再管用,但对于 a = a*(b+c),就很容易了:a *= b+c。

    • 如果需要将整数增大或减小 1,则根本不需要使用赋值。可以使用递增递减操作来代替:
    a++; // Increment. Increase a by 1
    b--; // Decrement. Decreases b by 1
    

    例 16.递增和递减

    这些操作都是一元操作,也就是说,它们只需要一个变量就能进行操作。此类运算有两种符号形式:前缀和后缀。

    前缀形式使用时,将首先执行操作,然后在表达式中使用结果。

    后缀形式使用时,将首先使用变量的旧值,然后变量值将变化 1:

    int a = 1;
    Print (++a); // 2, and a == 2
    Print (a++); // 2, but a == 3
    

      例 17.递增的前缀和后缀形式(递减的用法完全相同)

      • 通过 "级联",您可以连续使用多个赋值运算符。从右到左的操作顺序仍旧保留。
      int a=1, c=3;
      a = c = a+c; // first a+c (4), then c = 4, then a = c (i.e. a = 4)
      

      例 18."级联"赋值


      基本数据类型

      数据类型相对较多。

      其中有些是 "简单"(或 "基本")的。这些类型包括字符串、数字、日期、颜色等。其他类型则是"复杂"类型;MQL5 程序开发人员会创建此类类型。通常情况下,"复杂"数据类型是简单数据类型的组合,即为了更方便而将多个变量合并到一个数据块中。

      本文只介绍基本类型。我们将在下一部分讨论复杂类型的问题。

      整数类型

      整数是计算机"思考"的主要方式。

      计算机上的整数运算既简单又快速。但如果操作结果超出了一定的数值范围,就可能导致数据丢失。

      第二个要点:整数可以是"signed"(有符号)或 "unsigned"(无符号)的。

      如果数字是 "unsigned",则可以使用从 0 到最大值的数字。例如,占用 1 个字节的数字可以从 0 增加到 28-1 = 255,总共 256 个值。

      如果有人试图将数字 "256" 或 "-1" 写入这样的变量,就会出现 "溢出"。在这种情况下,结果将限制在相同的范围内 [0.255],而其余数据将丢失有时这样做可能有用,但在绝大多数情况下,最好使用其他方法进行此类转换。例如,可以使用余数运算符(本文稍后讨论)。最好使用能接受全部数据而不会丢失的变量类型。

      以 0 开头的类型(实际上是描述自然数的类型)的名称前面都有字母 "u"(用于unsigned)。

      "signed"数使用相同的数值范围,但被分成两半。前半部分存储负数,后半部分存储正数。也就是说,同样的单字节数字在[-128...127] 范围内是正确的。

      表格1 - 整数数据类型

      名称
      大小字节数
       最小值
      最大值
      char
      1(8 位)
      -128
      127
      uchar
      1(8 位)
      0
      255
      short
      2(16 位)
      -32768
      32767
      ushort
      2(16 位)
      0
      65535
      int
      4(32 位)
      -2147483648
      2147483647
      uint
      4(32 位)
      0
      4294967295
      long
      8(64 位)
      -9223372036854775808
      9223372036854775807
      ulong
      8(64 位)
       0  18446744073709551615

      在实践中,最常用的类型是 int(因为这种字写起来很快,而且这种类型的数据相当大)和 long(其大小足以满足绝大多数任务的需要,编译器可以优化字节码,使其在现代计算机上达到最佳性能)。

      不过,其他类型也很有用。

      布尔型

      该类型由bool关键字指定,占用1 个字节的内存,只能取两个值:truefalse

      如有必要,任何数字都可以用作逻辑数据。例如,如果数字等于 0,那么它就是 "false";在所有其他情况下,它就是 "true"。不过,为这种目的而使用数字时要非常小心。

      实数(又称浮点数)

      表 2.实数类型

      名称
       大小字节数 最小正值  最大值  
      float
      4(32 位)
      1.175494351e-38
      3.402823466e+38
      double
      8(64 位)
      2.2250738585072014e-308
      1.7976931348623158e+308

      现在的实际应用主要是"double"类型了,我已经很久没有在别人的代码中看到"float"类型了。这可能是为了与旧版本兼容。不过,在数据集非常大的情况下,它可以有效地节省内存空间。

      实数可以表示价格、货币数量和其他有用的概念。

      它们的取值范围比整数大得多。

      然而,计算机使用这些类型并不十分方便。首先,实数运算比整数运算稍慢。其次,由于格式的特殊性,计算结果的最后一位数几乎总是有误差。因此,在某些操作中,您可能得到 1.00000001,而不是 1.0;在另一些操作中,您可能得到 0.99999999。

      因此,如果需要比较两个实数,通常应取它们的差值,然后与某个小值进行比较,当然这个小值肯定要大于误差。这是一种更可靠的方法。

      日期和时间

      该类型用单词datetime 表示,在内存中占8 个字节

      该类型的每个变量都包含从1970 年 1 月 1 日到所需日期的秒数。因此,它是一个正整数

      最后的有效日期是3000 年 12 月 31 日。在我们有生之年,这已经足够了,所以我们不必担心 "2000 年问题"(如果你还记得的话)。

      有一些特殊的预定义常量:

      • __DATE__ — 编译日期
      • __DATETIME__ — 编译日期和时间
      • 您可以使用表达式__DATETIME__-__DATE__ — 它只描述编译时间,不包含日期。

      在书写字面量时,可以省略所有内容,将值写成D''(D 和两个单引号)。该符号等同于 __DATETIME__。不过,这样会降低代码的可读性。

      颜色

      MQL5 中的颜色由单独的类型 color 表示。在描述颜色时,可以使用固定值:

        color myColor1=C'100,200,30';
        color myColor2=C'0xFF,0x00,0x5A';
      

      例 19.使用十进制或十六进制数字描述颜色

      您还可以使用为网页颜色预定义的常量。颜色常量名称以 clr 开头(例如,clrBlue 表示蓝色)。在 MetaEditor 中键入clr或访问官方文档,即可查看常量的完整列表。

      在例 12 中,您可以看到每种颜色的描述都由三个片段组成。每个片段描述屏幕上一个点的红色、绿色或蓝色强度(红、绿、蓝 = RGB)。它们组合在一起,呈现出各种各样的色彩。

      通过混合红色和绿色,我们可以得到黄色、褐色和橙色的各种色调。

      红色和蓝色产生紫粉色调。

      绿色和蓝色呈现出不同的绿松石色、青色等。

      将这三种色调等比例混合,就会产生一系列灰色色调:从黑色(所有成分都处于 "关闭 "状态,即强度为 0)到白色(所有成分的最大强度都为 255(0xFF))。

      如果比例不相等,即每个成分的强度都与其他成分不同,则会产生显示器上的所有其他色调。绿色通常会使整体颜色变浅,而蓝色会使整体颜色变深。当然,一般来说,成分越亮,颜色就越浅(整体颜色也越浅)。

      表 3 举例说明了所有这些规则,我只是用编辑器中可用的颜色给单元格着色。

      在实际操作中,通常不需要知道每种颜色的数值,只需从一个特殊的调色板中选择颜色或传递一个预定义的常数即可。不管怎么说,我相信了解万事万物的运作原理是有益的。

      颜色数据在内存中占4个字节,但只使用其中3个字节。历史上曾发生过这种情况,对于任何可以使用这种颜色描述模型的程序来说,这是一个普遍的共识。

      表 3.颜色示例

      0, 0, 0 156, 15, 15 106, 0, 86 0, 49, 110 0, 110, 41 56, 37, 9 56, 37, 9
      51, 51, 51 191, 3, 3 133, 2, 108 0, 67, 138 0, 137, 44 243, 195, 0 87, 64, 30
      102, 102, 102 226, 8, 0 160, 39, 134 0, 87, 174 55, 164, 44 255, 221, 0 117, 81, 26
      153, 153, 153 232, 87, 82 177, 79, 154 44, 114, 199 119, 183, 83 255, 235, 85 143, 107, 50
      204, 204, 204 240, 134, 130 193, 115, 176 97, 147, 207 177, 210, 143 255, 242, 153 179, 146, 93
      255, 255, 255 249, 204, 202 232, 183, 215 164, 192, 228 216, 232, 194 255, 246, 200 222, 188, 133

      如果需要,可以像处理普通整数一样处理颜色。

      示例代码如下:

        color a = C'255,0,0';
        color b = C'0,255,0';
        color d = a+b;
        Print(a," ",b," ",d);
      

      例 20.在算术表达式中使用颜色

      结果如下:

      在算术表达式中使用颜色的结果

      图 9. 在算术表达式中使用颜色的结果

      枚举

      最后一种基本类型是枚举。

      在某些情况下,根据问题的具体情况,变量只能取某些值。例如,趋势可以是下降、上升或盘整。此外,只存在以下买入订单类型:买入(以市价买入)、止损买入(等待价格达到一定水平以实现突破)和限价买入(挂单,期待反弹)。一周内的天数总是一样的。我认为原则是明确的。

      在这种情况下,我们就可以使用枚举

      描述枚举包括三个步骤。

      1. 第一步,你需要创建列表本身,并以某种方式为其命名。生成的名称就是变量或函数的类型名称。这个名称与预定义类型的唯一区别是,它是我们自己得出的。
      2. 第二步,创建一个此类变量。
      3. 最后,在第三步中,你可以使用这个变量。
      例 15 展示了如何描述和使用枚举。为了说明这一点,我使用了方向描述 (DIRECTION),它只能使用三个值:"向上"(Upward)、"向下"(Downward)和 "旁边"(Aside)。

      //--- First step: creating a new list (new data type)
        enum ENUM_DIRECTION
         {
          Upward,
          Downward,
          Aside
         };
      
      //--- Second step: description (and, if necessary, initialization) of a variable of this type
        ENUM_DIRECTION next=Upward;
      
      //--- Third step: using the variable
        Print(next);
      

      例 21.枚举说明和用法

      通常情况下,枚举列表是在文件的开头创建的,紧接在预处理器指令之后。在这种情况下,我们应用程序的所有函数都可以使用它。

      虽然你可以在某个函数内部对其进行局部描述。这样,其他函数就无法看到该枚举。大多数情况下,这并没有什么意义,但你永远不知道会面临什么样的任务。

      枚举的元素名称在大括号内指定,中间用逗号隔开

      任何类型描述(包括枚举)的结尾大括号之后都必须有一个分号。其他区块的情况可能并非如此。

      语言中预定义的枚举名称是以大写字母书写的,这些名称以前缀 ENUM_ 开头。您可以随意(在规定范围内)命名您的枚举,但遵守相同的标准是一种良好的做法。

      枚举的内部表示形式是一个带符号 整数,在内存中占 4个字节

      如果我们尝试执行示例 21 中的代码,就会看到数字 0。这意味着,当我们让 MQL5 自行为枚举元素选择数字时,它会从零开始。

      但您也可以指定其他数字,只需明确设置即可:

      //--- First step: creating a new list (new data type)
        enum DIRECTION
         {
          Upward = 1,
          Downward = -1,
          Aside = 0
         };
      

      例 22.明确设置枚举值

      无需指定所有值。

      如果指定了某些值,而某些值没有指定,MQL5 将根据元素的顺序和最后一个最高数字自行选择数字。这意味着,在例 15 中,如果我们设置Upward = 1并删除所有其他初始化,那么 Downward 将等于 2,Aside 将等于 3。你应该自己检查一下。


      表达式和简单运算符

      当我们处理数据时,能够对数据进行比较、执行数学运算等非常重要。不同的表达式可用于不同的数据类型。

      比较运算符

      这些运算符对所有数据类型都有意义。

      比较结果逻辑型

      比较运算符如下:

      • 大于 ( > )、 
      • 小于 ( < )、 
      • 大于或等于 (>= )、 
      • 小于或等于 ( <= )、 
      • 等于 ( ==)、 
      • 不等于 (!= )

      所有这些操作的优先级都是一样的。

      比较字符串时,计算机将遵循编码中的字符排列。例如,大写字母 "A "在小写字母 "a "之前,因此会变小。因此:

      "An apple" < "a pal" //true

      例 23.比较字符串。大写字母小于小写字母

      如果一行中有多个相同字符,则选择第一个不相等的字符进行比较。

      "An apple" > "A pal" //true

      例 24.第一个字母相同

      例 24 中的表达式是正确的,因为编码中的空格位于字母字符之前,而且第一个字母是相同的。

      如果一个字符串已经结束,而第二个仍在继续,且开头相同,则认为结束的一个较小。示例:

      "An apple" < "An apple was found" //true

      例 25.不同的字符串长度

      算术运算

      结果是由表达式中使用的数据类型决定的。

      您可以对数字进行算术运算

      • 数字 ( -3) 前面的符号(有时称为 "一元 "减号);
      • 乘法 (*)、除法 (/)(整数向下舍入)、除法余数 (%)(仅适用于整数,5%2 == 1);
      • 加法 (+),减法 (-);
      • 递增 (++), 递减 (--)

      列表是按优先顺序排列的。

      不过,最好不要将普通表达式中的增量和减量与其他算术运算符混用,因为可能会出现结果未定义的情况。

      操作 (+) 也是为字符串定义的,但在这里指的是粘合(把两个短字符串粘成一个长字符串)。

      位操作

      结果是一个整数

      对于整数,还有以下位操作

      • 位反(~)
      • 右移(>>)
      • 左移(<<)
      • 位"与"(&)
      • 位"或"(|)
      • 位"异或"(^)

      如果您需要它们,那么您肯定不再是初学者了,您可以在语言文档中找到所需的信息。:-)

      列表是按优先顺序排列的。

      逻辑运算符

      结果是逻辑型值。

      • 逻辑反 ( ! )
      • 逻辑乘法 - 逻辑"与"(&&);
      • 逻辑加法 - 逻辑"或"(||)。

      列表是按优先顺序排列的。

      还有其他操作,将在其他文章中讨论。此外,我们还将在其他文章中详细讨论使用上述所有运算符的示例。目前,您可以使用您所理解的部分或查看语言文档。应该不会有什么特别困难的。


      类型转换

      有时,一个算术表达式涉及多种数据类型。例如,我们经常使用 Print 函数打印字符串和数字,在本文中我们甚至还遇到了颜色。

      结果会是什么类型?在这里,我们有两种选择:要么由我们自己决定最终结果,要么相信编译器。

      当然,编译器是很聪明的,它能想出办法来。但并非总是如此。

      因此,让我们来看看编译器会做些什么,以及可以"手动 "做些什么,以避免丢失重要数据,在编译过程中不会收到警告,并对编译结果充满信心。

      编译器做了哪些事?

      首先,如果表达式使用了相同类型的数据,那么结果也将是相同类型的。这是最简单的情况。

      如果涉及不同的类型,编译器会尝试将结果扩展为最准确的类型。例如,如果我们尝试将一个 4 字节整数(int)与一个日期(datetime)相加,我们将得到一个日期类型(因为其范围更广)。

      整数字面量属于 int 类型,浮点数通常属于 double 类型,除非以小写字母 "f "结尾:

      5 + 3.4f + 4.25 // The result is double, since 5 is first converted to float, and then 4.25 sets double precision

      例 26.使用固定值时的类型转换

      帮助文档包括类型转换优先级方案:

      类型转换优先级

      图 10.类型转换优先级

      需要注意的是,有符号类型和无符号类型相互转换可能会导致数据丢失,而转换为浮点类型可能会导致精度损失。

      因此,如果您不确定编译器将如何转换数据,可以考虑人工指定将哪些数据转换为哪些数据。

      如果需要将结果(或特定值)转换为特定类型,可以这样做:

      • 将结果写入某个类型的变量。这种方法本质上是自动转换的一种变体,因此必须谨慎使用。
      • 使用特殊的数据转换函数
      • 使用类型转换的简单形式。
      (int)a+b // converts a to an integer. b remains unchanged
      double (c+d) // absolutely similar to the previous one. In this case, the result of the summation is converted
      
      // and so on - you can use any suitable type
      
      

      例 27.类型转换的简单形式

      不要忘记,括号可以更改操作顺序,因为括号的优先级最高。如果不确定,请使用括号。


      结论

      我们已经学习了有关基本数据类型、变量和表达式的大量理论知识。如果你理解了这篇文章和下一篇文章的内容,那么你几乎就不再是初学者了,而是会进入一个更高的层次。如果你理解了变量(本文的内容)和函数(将在下一篇文章中介绍)的工作原理,那么你就可以自信地继续学习更复杂的主题,比如 OOP。

      OOP(面向对象编程)被认为是一项复杂的内容。其实,思想观念方面的困难多于技术方面的困难。

      对于那些不理解某些要点的人,我建议他们慢慢地重新阅读这篇文章(一次或多次),一个概念一个概念地读,检查代码中提到的所有内容。

      对于什么都已经明白,又不想等到我准备好下一篇文章的人,我建议他们编写自己的脚本,以显示操作的交易品种和余额的有用信息,从而让等待的时间更充实。其中大部分信息可从 AccountInfoSymbolInfo 函数族中获取。

      尝试使用 MetaEditor 查找这些系列中每个函数的全名,然后在帮助中查找它们的描述。有了这些说明和本文所涉及的材料,创建这个脚本就不需要您花费太多精力了。

      备注:标准库中有这样一个脚本示例。如果您不想编写自己的脚本,可以尝试分析现成的脚本。如果你能编写自己的程序,请将其与标准程序库中的程序进行比较。

      本文由MetaQuotes Ltd译自俄文
      原文地址: https://www.mql5.com/ru/articles/13749

      MQL5 中的定量分析:实现有前途的算法 MQL5 中的定量分析:实现有前途的算法
      我们将分析什么是定量分析,以及主要参与者如何运用定量分析的问题。我们将用 MQL5 语言创建一种定量分析算法。
      种群优化算法:模拟各向同性退火(SIA)算法。第 II 部分 种群优化算法:模拟各向同性退火(SIA)算法。第 II 部分
      第一部分专注于众所周知、且流行的算法 — 模拟退火。我们已经通盘研究了它的利弊。本文的第二部分专注于算法的彻底变换,将其转变为一种新的优化算法 — 模拟各向同性退火(SIA)。
      在 MQL5 中创建做市商算法 在 MQL5 中创建做市商算法
      做市商是如何运作的?让我们探讨一下这个问题,创建一个初级的做市商算法。
      图表上的历史仓位及其盈利/亏损图指标 图表上的历史仓位及其盈利/亏损图指标
      在本文中,我将探讨根据交易历史获取已平仓头寸信息的选项。此外,我将创建一个简单的指标,以图表的形式显示每个柱形上仓位的大致盈利/亏损。