算术运算
算术运算包括 5 个二进制运算,即加、减、乘、除和模除,以及 2 个一元运算,即正号和负号。下表给出了每种运算使用的符号。
在包含示例的列中,e1 和 e2 是任意子表达式。用左(从左向右)和右(从右向左)标记结合性。第一列中的数字可以被视为执行运算的优先级。
优先级 |
符号 |
说明 |
示例 |
结合性 |
---|---|---|---|---|
2 |
+ |
一元加法 |
+e1 |
右 |
2 |
- |
一元减法 |
-e1 |
右 |
3 |
* |
乘法 |
e1 * e2 |
左 |
3 |
/ |
除法 |
e1 / e2 |
左 |
3 |
% |
模除法 |
e1 % e2 |
左 |
4 |
+ |
加法 |
e1 + e2 |
左 |
4 |
- |
减法 |
e1 - e2 |
左 |
表中的顺序为降序优先级:一元加法和减法优先于乘法和除法,而乘法和除法优先于加法和减法。
double a = 3 + 4 * 5; // a = 23 |
事实上,一元加法在计算中没有任何作用,但可以用于更好地可视化表达式。一元减法可反转其操作数的符号。
算术运算用于数字类型或可以强制转换为数字类型的类型。计算结果是一个右值。在计算中,整数操作数的存储位置通常会扩展到所用整数中“最大值”或扩展到 int(如果所有整数类型都更小),并被强制转换为一种通用类型。有关更多详细信息,请参见 类型强制转换。
bool b1 = true;
|
在本示例中,b1 变量“扩展” 至值为 1 的 int 类型。反转符号得 -1,而类型强制转换为 bool 再反转得到 true(因为 -1 非零)。不建议在算术计算中使用逻辑类型。
整数相除结果为整数,即小数部分(如有)被忽略。可以使用 ExprArithmetic.mq5 脚本验证这一点。
int a = 24 / 7; // ok: a = 3
|
虽然 c 变量被描述为 double,但是该变量的初始化表达式中包含整数;因此,执行的是整数除法。要执行带小数部分的除法,必须至少有一个操作数是实数类型(第二个操作数也将被强制转换为实数类型)。
double d = 24.0 / 7; // ok: d = 3.4285714285714284 |
% 运算符计算整数除法的余数(仅适用于两个整数类型的操作数)。
int x = 11 % 5; // ok: x = 1
|
操作数具有不同符号时,使用 * 和 / 运算符的结果为负数。% 运算符遵循以下规则:
- 如果 % 运算符的除数为负,则符号“转义”;
- 如果 % 运算符的被除数为负,则结果为负;
使用模除法的替代计算可以轻松验证这一点:m % n = m - m / n * n。切记,整数除法 m / n 的结果将被舍入;所以一般情况下,m / n * n 不等于 m。
在 数组特性一节中,我们深入研究了多维数组可以用一维数组来表示的思想(通过重新计算数组元素的索引)。我们还提供了通过二维数组的坐标(列号为 X,行号为 Y,字符串长度为 N)获得一维数组的查询索引的公式。
index = Y * N + X |
% 运算允许我们执行更便捷的反向计算,即通过索引穿透法求解 X 和 Y:
Y = index / N
|
如果在计算表达式期间的某个阶段获得一个不可表示的结果 NaN(非数字,如无穷大、负数的平方根等),所有后续的运算也会产生一个 NaN。可以使用 MathIsValidNumber 函数判定结果是否为正常数值(参见 数学函数)。
double z = DBL_MAX / DBL_MIN - 1; // inf: Not A Number |
此处是对 NaN(除法运算的结果)进行了减法运算,结果再次得到 NaN。
为字符串定义加法运算,并执行连接,即组合字符串。
string s = "Hello, " + "world!"; // "Hello, World!" |
禁止对字符串进行其他运算。