Найден этот умный трюк с использованием «волшебных масок» в «Искусство программирования, часть 4», который делает это в O (log (n)) времени для n-разрядного числа. [с логическим (n) дополнительным пространством]. Типичные проверки решений для установленного бита - это O (n) или O (n) дополнительное пространство для таблицы поиска, поэтому это хороший компромисс.
Магические маски:
m0 = (...............01010101)
m1 = (...............00110011)
m2 = (...............00001111)
m3 = (.......0000000011111111)
....
Основная идея: нет конечных нулей в x = 1 * [(x & amp; m0) = 0] + 2 * [(x & amp; m1) = 0] + 4 * [(x & amp; m2) = 0] + ...
int lastSetBitPos(const uint64_t x) {
if (x == 0) return -1;
//For 64 bit number, log2(64)-1, ie; 5 masks needed
int steps = log2(sizeof(x) * 8); assert(steps == 6);
//magic masks
uint64_t m[] = { 0x5555555555555555, // .... 010101
0x3333333333333333, // .....110011
0x0f0f0f0f0f0f0f0f, // ...00001111
0x00ff00ff00ff00ff, //0000000011111111
0x0000ffff0000ffff,
0x00000000ffffffff };
//Firstly extract only the last set bit
uint64_t y = x & -x;
int trailZeros = 0, i = 0 , factor = 0;
while (i < steps) {
factor = ((y & m[i]) == 0 ) ? 1 : 0;
trailZeros += factor * pow(2,i);
++i;
}
return (trailZeros+1);
}
foo (args: _ *)
делает трюк. Вместо применения последовательности в качестве одного аргумента каждый элемент в последовательности будет использоваться в качестве аргумента.
args: _ *
– Richeek 16 June 2015 в 21:31foo
, которая делает преобразование. Таким образом, ваш оригинальный вызовfoo
будет работать, если ваш код пользователя не должен беспокоиться об этом. Сказав, что еслиfoo
потребовал набор, такой какSeq
, а не примитивный тип, такой какString
, инвариантность коллекций scala затрудняла бы любые разумное использование вашего api. Как будто списки переменных аргументов и стандартные коллекции библиотек не были разработаны для случаев взаимного использования за пределами ванили. – matanster 27 November 2015 в 09:17foo (args: _ *)
, мы надеемся, будет немного более загадочным (обратите внимание на добавленное пространство между операторами). [D3]: означает, что выполняется запись типа типа . [D4] _ * является специальным экземпляром типа acription: a vararg expansion . – José Andias 5 July 2018 в 09:59