Показать сообщение отдельно
  #8 (permalink)  
Старый 23.12.2011, 09:56
sinistral
Посмотреть профиль Найти все сообщения от melky
 
Регистрация: 28.03.2011
Сообщений: 5,418

суть укладывается в 2 строчки

x = 'x'; 
s = ''; 
s += x; /* Now s = 'x' */ 
x += x; /* Now x = 'xx' */ 
x += x; /* Now x = 'xxxx' */ 
x += x; /* Now x = 'xxxxxxxx' */ 
s += x; /* Now s = 'xxxxxxxxx' as desired */

it's bullshit.
function stringFill3(x, n) {
    var s = '';
    for (;;) {
        if (n & 1) s += x;
        n >>= 1;
        if (n) x += x;
        else break;
    }
    return s;
}

it's better.
(по скорости, конечно же)
и всё.
осталось только проанализировать, КАК побитовые операции с числами могут иметь какой-то толк с НЕчислами.

PS насчёт скорости. разница в 1.8 раза в FF. в хроме коэффициент 2.5.

PSS краткий разбор (если можно так назвать) этого кода.
function stringFill3(x, n) {
    var s = '';
    for (;;) {
        if (n & 1) s += x;
        n >>= 1;
        if (n) x += x;
        else break;
    }
    return s;
}

сначала создаёт s (результат), далее идёт "бесконечный" цикл (потому что будет работать, пока не прервёшь). таким образом, можно было не выпендриваться и написать цикл через while. и смотрелось бы понятнее.

в каждой итерации цикла к строке s прибавляется, если n & 1. да, конечно, мы все знаем, что & возвращает единичку только для единичек, но что это значит на практике ?
распишем двоичные представления чисел от 1 до 5 (включительно)
Код:
1       0001
2       0010
3       0011
4       0100
5       0101
операция <число> & 1 будет возвращать 1 для тех чисел, у которых последняя цифра (1 для 5, 0 для 4) совпадает с 1 (т.к. единица осталась единицей, то совпадение считается только по последней колонке. если бы вместо единицы с правой стороны оператора было какое-нибудь 0101110, то совпадения высчитывалось для всех пар)
т.е. если мы пройдёмся по всем цифрам из [1,5] с & 1 , то получим это :
1  1
2  0
3  1
4  0
5  1

проверку на нечётность не напоминает ? таким образом , <число> & 1 эквивалентно проверке числа на нечётность. (<число> % 2)

идём дальше.

n >> 1 будет, как известно, будет сдвигать биты один раз (с правой стороны) в числе n. но что это значит ? возьму тот же промежуток.
Код:
1       0001
2       0010
3       0011
4       0100
5       0101
если мы сделаем 2 >> 1, то сдвинем биты в числе 2 в двоичном представлении вправо один раз.
Код:
1 = 0001
1 >> 1
0000 (0)

2  = 0010 
2 >> 1
0001 (1)

5 = 0101
5 >> 1
0010 (2)
в итоге, для того промежутка <число> >> 1 будет иметь такой результат :
0 0
1 0
2 1
3 1
4 2
5 2

похоже на итератор (--,++)

if (n) x += x; будет работать, пока n не дойдёт до нуля. т.к. перед этой проверкой стоит сдвиг вправо, то, можно сказать, цикл кончится (там break дальше, я не включил), когда n станет равным 0. т.е. на каждой итерации к строке добавления (строка результата - s) будет добавляться она же. что это значит?
посмотрим.
x = 'x';
n = 5;
s = '';

// I итерация, n = 5
n & 1 == 1 /*=>*/ s = s + x; // s = 'x'.
n = n >> 1; // n = 2
x = x+x; // 'xx';

// II, n = 2
n & 1 === 0;
n = n >> 1; // n = 1
x = x+x;// 'xx' + 'xx' => 'xxxx'

// III, n = 1
n & 1 /*=>*/ s = s+x; // 'x'+'xxxx' => 'xxxxx'
n = n >> 1 // n = 0
n == 0 /*=>*/ break

// res : 'xxxxx'.


Вывод :

обычный цикл для повторения строки, но оптимизированный :
  1. заменой всех операций с числами на побитовые (переход от десятичной системе к двоичной)
  2. уменьшением количества итераций в несколько раз

Последний раз редактировалось melky, 23.12.2011 в 11:24.
Ответить с цитированием