4.2 范围

范围(range)是编写具有等间距元素的行向量的一种便捷方式。范围表达式由范围中第一个元素的值、元素之间增量的可选值以及范围中元素不会超过的最大值来定义。基数、增量和限制用冒号(:字符)分隔,并且可以包含任何算术表达式和函数调用。如果省略增量,则假定为 1。例如,范围

1 : 5

定义了一组值 [ 1, 2, 3, 4, 5 ],而范围

1 : 3 : 5

定义了一组值 [ 1, 4 ]

虽然范围常量指定的是一个行向量,但 Octave 通常不会将范围常量转换为向量,除非有必要这样做。这允许您编写像 1 : 10000 这样的常量,而无需在典型工作站上占用 80,000 字节的存储空间。

一个常见的需要将范围转换为向量的情况是当它们出现在向量内部时(即在方括号内)。例如,尽管

x = 0 : 0.1 : 1;

x 定义为 double_range 类型的变量,占用 24 字节内存,而表达式

y = [ 0 : 0.1 : 1];

y 定义为 matrix 类型,占用 88 字节内存。

这种节省空间的优化可以通过 optimize_range 函数来禁用。

 
val = optimize_range ()
old_val = optimize_range (new_val)
old_val = optimize_range (new_val, "local")

查询或设置是否使用一种特殊的节省空间的格式来存储范围。

默认值为 true。如果将此选项设置为 false,Octave 将把范围存储为完整的矩阵。

当从函数内部使用 "local" 选项调用时,该设置会在函数及其调用的任何子例程中局部更改。退出函数时恢复原始设置。

另请参阅: optimize_diagonal_matrixoptimize_permutation_matrix

请注意,范围的上限(或下限,如果增量为负)并不总是包含在值集中。这在某些上下文中是有用的。例如:

## x is some predefined range or vector or matrix or array
x(1:2:end) += 1;   # 递增所有奇数索引元素
x(2:2:end) -= 1;   # 递减所有偶数索引元素

无论 x 有奇数个元素还是偶数个元素,上述代码都能正确工作:无需区别对待这两种情况。

Octave 使用浮点运算来计算范围中的值。因此,使用浮点值定义范围可能会导致以下陷阱:

a = -2
b = (0.3 - 0.2 - 0.1)
x = a : b

由于浮点舍入,b 可能恰好等于零,也可能不等于零;如果不等于,则可能大于零或小于零,因此最终范围 x 可能包含也可能不包含零作为其最终值。类似地:

x = 1.80 : 0.05 : 1.90
y = 1.85 : 0.05 : 1.90

并不像看起来那样可预测。截至 Octave 8.3,得到的结果是 x 有三个元素(1.80、1.85 和 1.90),而 y 只有一个元素(1.85,但不包含 1.90)。因此,在范围中使用浮点数时,改变范围的起始点很容易影响范围的结束点——尽管在上述示例中结束值本身并未被修改。

为避免在范围中使用浮点数时出现此类陷阱,可以使用以下模式之一。将前面的代码改为:

x = (0:2) * 0.05 + 1.80
y = (0:1) * 0.05 + 1.85

使用整数构造范围,然后转换为浮点数,使整个表达式安全且可在不同平台、编译器和编译器设置之间重复。如果您知道元素的数量,可以使用 linspace 函数(请参见特殊实用矩阵),该函数会包含范围的端点。您还可以合理使用 roundfloorceilfix 等函数来设置限制和增量,避免浮点舍入的干扰。例如,前面的示例可以通过以下方式之一变得更安全:

a = -2
b = round ((0.3 - 0.2 - 0.1) * 1e12) / 1e12   # 四舍五入到 12 位
c = floor (0.3 - 0.2 - 0.1)                   # 向下取整为整数
d = floor ((0.3 - 0.2 - 0.1) * 1e12) / 1e12   # 向下取整到 12 位
x = a : b
y = a : c
z = a : d

如果范围表达式的结果为空,则 Octave 返回一个空的 matrix,而不是空的 double_range。类似地,如果范围中只有一个元素,则 Octave 返回一个 scalar,而不是只有一个元素的 double_range


版权所有 © 2024-2026 Octave中文网

ICP备案/许可证号:黑ICP备2024030411号-4