Чтобы представить " эксклюзивный " набор параметров n
(т. Е. Должен быть выбран только один), нам требуется не менее ceil(log2(n))
битов. Например, опция k
может быть представлена числом k
в базе- 2
.
Для представления " ортогонального " набора параметров n
(т. Е. Может быть выбрана любая комбинация размера 0, 1, ..., n
), нам требуется не менее n
битов. Например, параметры k0, k1, k2
могут быть представлены двоичным числом, биты которого равны нулю, за исключением битов 0, 1, 2
.
Таким образом, чтобы представить несколько наборов опций одновременно, мы складываем количество битов, необходимое для каждого набора опций (в зависимости от того, является ли он "эксклюзивным" или "ортогональным"), чтобы получить общее количество требуемых битов.
Короче говоря, для выбора значений перечисления,
- «Эксклюзивный» параметр
k
использует k << r
- опция "ортогональный"
k0, k1, ..., k{n-1}
использует 0x1 << r, 0x1 << (r+1), ..., 0x1 << (r+n-1)
где смещение r
- это количество битов, использованных предыдущими наборами опций.
Пример того, как автоматизировать эту конструкцию , на Java:
/**
* Construct a set of enum values, for the given sizes and types
* (exclusive vs orthogonal) of options sets.
*
* @param optionSetSizes
* number of elements in each option set
* @param isOptionSetExclusive
* true if corresponding option set is exclusive, false if
* orthogonal
* @returns
* array of m elements representing the enum values, where
* m is the sum of option set sizes. The enum values are
* given in the order of the option sets in optionSetSizes
* and isOptionSetExclusive.
*/
int[] constructEnumValues(
int[] optionSetSizes,
boolean[] isOptionSetExclusive)
{
assert optionSetSizes.length == isOptionSetExclusive.length;
// determine length of the return value
int m = 0;
for (int i = 0; i < optionSetSizes.length; i++) m += optionSetSizes[i];
int[] vals = new int[m];
int r = 0; // number of bits used by the preceding options sets
int c = 0; // counter for enum values used
for (int i = 0; i < optionSetSizes.length; i++)
{
// size of this option set
int n = optionSetSizes[i];
// is this option set exclusive?
boolean exclusive = isOptionSetExclusive[i];
for (int k = 0; k < n; k++)
{
vals[c] = (exclusive) ? (k << r) : (0x1 << (r + k));
c++;
}
r += (exclusive) ? (int) Math.ceil(Math.log(n)/Math.log(2)) : n;
}
return vals;
}