4.2 Диапазоны ¶
A 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 как переменную типа 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_matrix, optimize_permutation_matrix.
Обратите внимание, что верхняя (или нижняя, если приращение отрицательное) граница диапазона не всегда включается в множество значений. Это может быть полезно в некоторых контекстах. Например:
## x is some predefined range or vector or matrix or array x(1:2:end) += 1; # increment all odd-numbered elements x(2:2:end) -= 1; # decrement all even-numbered elements
Этот код работает правильно, независимо от того, содержит ли 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 (см. Специальные вспомогательные матрицы), которая будет включать конечные точки диапазона. Вы также можете разумно использовать round, floor, ceil, fix, и т.д., чтобы установить пределы и приращение без вмешательства округления чисел с плавающей точкой. Например, предыдущий пример можно сделать более безопасным и воспроизводимым с помощью одного из следующих:
a = -2 b = round ((0.3 - 0.2 - 0.1) * 1e12) / 1e12 # rounds to 12 digits c = floor (0.3 - 0.2 - 0.1) # floors as integer d = floor ((0.3 - 0.2 - 0.1) * 1e12) / 1e12 # floors at 12 digits x = a : b y = a : c z = a : d
При добавлении скаляра к диапазону, вычитании скаляра из него (или вычитании диапазона из скаляра) и умножении на скаляр Octave попытается избежать распаковки диапазона и сохранить результат в виде диапазона, если это безопасно. Например, выполнение
a = 2*(1:1e7) - 1;
приведёт к тому же результату, что и 1:2:2e7-1, но без создания вектора с десятью миллионами элементов.
Использование нуля в качестве приращения в записи с двоеточием, как в 1:0:1, запрещено, потому что при определении количества элементов диапазона произойдёт деление на ноль. Однако диапазоны с нулевым приращением (т. е. все элементы равны) полезны, особенно при индексировании, и Octave позволяет их создавать с помощью встроенной функции ones. Обратите внимание, что, поскольку диапазон должен быть строчной матрицей, ones (1, 10) создаёт диапазон, в то время как ones (10, 1) — нет.
При разборе Octave выражения диапазона проверяет элементы выражения, чтобы определить, являются ли все они константами. Если это так, он заменяет выражение диапазона одной константой диапазона.
© 1996–2023 The Octave Project Developers
Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies.
Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one.Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions.
https://docs.octave.org/v9.2.0/Ranges.html