Всегда ли верхние границы индексированных диапазонов считаются эксклюзивными? - PullRequest
7 голосов
/ 14 марта 2010

Таким образом, в Java, когда задан индексированный диапазон, верхняя граница почти всегда является исключительной.

С java.lang.String:

substring(int beginIndex, int endIndex)

Возвращает новую строку, которая является подстрокой этой строки. Подстрока начинается с указанного beginIndex и продолжается до символа с индексом endIndex - 1

С java.util.Arrays:

copyOfRange(T[] original, int from, int to)

from - начальный индекс копируемого диапазона включительно
to - конечный индекс диапазона, который будет скопирован, исключая.

С java.util.BitSet:

set(int fromIndex, int toIndex)

fromIndex - индекс первого устанавливаемого бита.
toIndex - индекс после последнего установленного бита.

Как вы можете видеть, похоже, что Java пытается согласовать соглашение о том, что верхние границы являются исключительными.

Мои вопросы:

  • Это официальная официальная рекомендация?
  • Есть ли заметные нарушения, о которых нам следует опасаться?
  • Есть ли название для этой системы? (аля "на основе 0" против "на основе 1")

УТОЧНЕНИЕ: я полностью понимаю, что коллекция N объектов в системе на основе 0 индексируется 0..N-1. Мой вопрос заключается в том, что если указан диапазон (2,4), это может быть либо 3 элемента, либо 2, в зависимости от системы. Как вы называете эти системы?

СНОВА, проблема не в системе "first index 0 last index N-1" vs "first index 1 last index N" system; это известно как система на основе 0 против 1.

Проблема в том, что "в (2,4) 3 элемента" против "в системах (2,4)" 2 элемента. Как вы их называете, а одно официально санкционировано над другим?

Ответы [ 6 ]

5 голосов
/ 14 марта 2010

В общем да. Если вы работаете на языке с C-подобным синтаксисом (C, C ++, Java), то массивы индексируются с нулевым индексом, а большинство структур данных с произвольным доступом (векторы, списки массивов и т. Д.) Будут индексироваться с нулевым индексом. также.

Начало индексов с нуля означает, что размер структуры данных всегда будет на один больше, чем последний действительный индекс в структуре данных. Конечно, люди часто хотят знать размер, и поэтому удобнее говорить о размере, чем о последнем действительном индексе. Люди привыкли говорить об окончании индексов эксклюзивно, потому что массив a[] длиной n элементов имеет свой последний действительный элемент в a[n-1].

Существует еще одно преимущество использования исключительного индекса для конечного индекса, который заключается в том, что вы можете вычислить размер подсписка, вычтя включающий начальный индекс из исключительного конечного индекса. Если я позвоню myList.sublist(3, 7), то получу подсписок с элементами 7 - 3 = 4. Если бы метод sublist() использовал инклюзивные индексы для обоих концов списка, то мне нужно было бы добавить еще 1, чтобы вычислить размер подсписка.

Это особенно удобно, когда начальный индекс является переменной: получение подсписка myList, начинающегося с i длиной 5 элементов, составляет всего myList.sublist(i, i + 5).

С учетом всего вышесказанного вам следует всегда читать документацию API, а не предполагать, что данный начальный или конечный индекс будет включающим или исключающим. Кроме того, вы должны документировать свой собственный код, чтобы указать, являются ли какие-либо границы включающими или исключающими.

2 голосов
/ 14 марта 2010

Кредит идет к FredOverflow в его комментарии, говоря, что это называется «полуоткрытый диапазон». Итак, предположительно, коллекции Java можно описать как « 0 на основе полуоткрытых диапазонов ».

Я собрал некоторые обсуждения о полуоткрытых и закрытых диапазонах в других местах:


silicbrain.com - 16 веских причин использовать полуоткрытые диапазоны (отредактировано для краткости):

  • Количество элементов в диапазоне [n, m) равно m-n (а не m-n+1).
  • Пустой диапазон - [n, n) (а не [n, n-1], что может быть проблемой, если n - это итератор, уже указывающий на первый элемент списка, или n == 0).
  • Для чисел с плавающей запятой можно написать [13, 42) (вместо [13, 41.999999999999]).
  • +1 и -1 почти никогда не используются при работе с диапазонами. Это преимущество, если они дорогие (как и для фиников).
  • Если вы напишите находку в диапазоне, тот факт, что ничего не было найдено, может быть легко указан путем возврата конца в качестве найденной позиции: if( find( [begin, end) ) == end) ничего не найдено.
  • В языках, в которых индексы массива начинаются с 0 (например, C, C ++, JAVA, NCL), верхняя граница равна размеру.

Полуоткрытые и закрытые диапазоны

Преимущества полуоткрытых диапазонов:

  • Допустимы пустые диапазоны: [0 .. 0]
  • Легко для поддиапазонов перейти к концу оригинала: [x .. $]
  • Простота разделения диапазонов: [0 .. x] и [x .. $]

Преимущества закрытых диапазонов:

  • Symmetry.
  • Возможно, легче читать.
  • ['a' ... 'z'] не требует неловкости + 1 после 'z'.
  • [0 ... uint.max] возможно.

Последний пункт очень интересный. Очень неудобно писать предикат numberIsInRange(int n, int min, int max) с полуоткрытым диапазоном, если Integer.MAX_VALUE может быть легально в диапазоне.

2 голосов
/ 14 марта 2010

На основе 0 до n-1 .

Список / Массив содержит 10 элементов 0-9 проиндексированных.

Вы не можете иметь индексированный список на основе 0, равный 0-n, где cout равен n, который включает элемент, который не существует ...

Это типичный способ работы вещей.

  1. Да .
  2. Диапазоны / листы / рабочие книги Excel.
  3. Указатель (информационные технологии)
0 голосов
/ 14 марта 2010

Простой способ представить полуоткрытые диапазоны таков: первый член определяет начало элементов в диапазоне, а второй - начало элементов после диапазона. Имейте это в виду, и все это имеет больше смысла. Кроме того, во многих случаях арифметика работает лучше, согласно ответу @polygenelubricants.

0 голосов
/ 14 марта 2010

Индексы в массиве , такие как структуры данных, действительно всегда основаны на 0. String в основном поддерживается char[]. Структура Collections находится под капотом на основе массивов и так далее. Это облегчает проектирование / поддержание / использование API без изменения способа скрытого доступа к нужным элементам в массиве.

Однако существуют некоторые «исключения», такие как основанные на индексах параметров методы PreparedStatement и основанные на индексах столбцов методы получения ResultSet. Они основаны на 1. За кулисами они также не представляют собой массив значений.

Это, вероятно, подняло бы новый вопрос: «Почему индексы массива основаны на нуле?». Теперь наш уважаемый ученый программист E.W. Дейкстра объясняет здесь почему он должен начинаться с нуля.

0 голосов
/ 14 марта 2010

Эта практика была введена Джошем Блохом в API коллекций как контракт.

После этого это стало стандартом в java, и когда кто-либо решает создать публичную библиотеку, он предполагает, что он должен соблюдать договор, потому что пользователи ожидают увидеть уже известное поведение в новых библиотеках.

...