Страницы

Поиск по вопросам

пятница, 19 октября 2018 г.

не пойму реализацию strlen

здравствуйте, нарыл тут на просторах реализацию сишной функции strlen :
/* Magic numbers for the algorithm */ #if LONG_BIT == 32 static const unsigned long mask01 = 0x01010101; static const unsigned long mask80 = 0x80808080; #elif LONG_BIT == 64 static const unsigned long mask01 = 0x0101010101010101; static const unsigned long mask80 = 0x8080808080808080; #else #error Unsupported word size #endif
#define LONGPTR_MASK (sizeof(long) - 1)
/* * Helper macro to return string length if we caught the zero * byte. */ #define testbyte(x) \ do { \ if (p[x] == '\0') \ return (p - str + x); \ } while (0)
size_t strlen(const char *str) { const char *p; const unsigned long *lp;
/* Skip the first few bytes until we have an aligned p */ for (p = str; (uintptr_t)p & LONGPTR_MASK; p++) if (*p == '\0') return (p - str);
/* Scan the rest of the string using word sized operation */ for (lp = (const unsigned long *)p; ; lp++) if ((*lp - mask01) & mask80) { p = (const char *)(lp); testbyte(0); testbyte(1); testbyte(2); testbyte(3); #if (LONG_BIT >= 64) testbyte(4); testbyte(5); testbyte(6); testbyte(7); #endif }
/* NOTREACHED */ return (0); }
можете прокомментировать зачем такой треш?


Ответ

Это реализация strlen, которая работает не побайтно, а пословно. Для того она и сделана: чтобы ради пущей эффективности читать и анализировать данные из памяти не одиночными байтами, а сразу выровненными словами длиной 32 или 64 бита.
Для достижения выравнивания начальная часть строки (до требуемой границы выравнивания), обрабатывается побайтно, то есть обычным способом.
Далее строка читается пословно. Каждое прочитанное слово обрабатывается при помощи следующего бит-хака
if ((*lp - mask01) & mask80)
который анализирует все прочитанное слово (т.е. фактически "параллельно" анализирует все его байты) и приблизительно отвечает на вопрос о том, есть ли в слове *lp нулевой байт. Если данная проверка дает положительный ответ, то код под этим if при помощи макро testbyte выясняет уже, в какой точной позиции он находился.
"Приблизительность" проверки в данном случае заключается в том, что условие в if иногда может дать положительный ответ даже в случае слова без нулевого байта - если в слове присутствуют байты с единицей в старшем бите. Т.е. эта проверка допускает "ложные срабатывания" и, как следствие, вызывает ненужную побайтовую проверку через testbyte, но на корректность результата это не влияет. Строки, составленные из символов с кодами не выше 128 будут обрабатываться эффективно.
Слова же, в которых нулевой байт содержится, этой проверкой будут заведомо обнаружены.
Более сложная версия условия, основанная на тех же масках
if ((*lp - mask01) & ~*lp & mask80)
гарантировала бы точное определение наличия нулевого байта в слове, но авторы, очевидно, решили, что эффективнее будет работать именно их приближенный вариант (скорее всего потому, что код рассчитан на строки из символов латинского алфавита).
Теоретически, такая реализация обладает одной формальной проблемой: при пословном чтении содержимого строки может получиться так, что последнее читаемое слово будет "торчать" за пределы самой строки и выделенной для нее памяти. На практике это не приводит к проблемам, так как выделение и/или защита памяти обычно делаются по границам, выровненным как минимум до размера полного слова. Однако подобные "вылеты" могут вызвать жалобы от средств динамического анализа кода, типа valgrind.

Классификация ip адресов

Что такое адрес произвольной рассылки (anycast)? Для чего он нужен?


Ответ

Any - любой, cast - бросать
Anycast - технология маршрутизации, предоставляет отправку пакета "первому попавшемуся" в anycast группе. Т.е. кто первый получил пакет - его и обрабатывает. Остальные участники Anycast группы этого пакета уже не увидят.
Если простым языком, то один и тот же IP-адрес назначается нескольким серверам, расположенным в разных местах и когда делается запрос по адресу - выбирается ближайший (чем меньше точек прохода пакета, тот ближе)
Более подробно в статье с Habrahabr:
Смысл метода Anycast заключается в анонсировании одинакового префикса IP-адресов одновременно из нескольких точек сети через протокол BGP. В результате данные передаются по наиболее короткому маршруту — на ближайший узел, которому присвоен анонсированный IP-адрес. При этом понятие «короткий маршрут» в данном случае трактуется не в географическом, а в топологическом смысле.

В чем смысл текстовых шаблонов T4 и когда их имеет смысл использовать?

В чем смысл текстовых шаблонов T4? По сути, этого же можно добиться с помощью динамической компиляции. Доступ к исходному коду так же не даёт никаких преимуществ, так как править его не имеет смысла из за перегенерации.


Ответ

Если вы имеете в виду T4, то их смысл — встроенный в систему шаблонизатор/DSL. T4 используется в двух вариантах: времени компиляции и времени выполнения.
T4 времени выполнения обычно используется как шаблонизатор, и означает, что вы можете легко генерировать текстовые файлы, в которых большая часть текста постоянна, а куски необходимо генерировать программно. Простой пример — шаблон письма, в который нужно вставить имя адресата, адрес и наименование товара.
Но гораздо более интересным является T4 времени разработки. Эта штука позволяет вам генерировать код на этапе компиляции (точнее, даже до неё). То есть, у вас появляется ещё одно прекрасное (хотя и немного неуклюжее — если не сравнивать с шаблонной магией Александреску) средство для настоящего метапрограммирования. Причём в отличие от решений, которые вы могли бы соорудить на коленке, T4 встроен в Visual Studio, и сгенерированные файлы просто видны в дереве Solution Explorer'а, и подхватываются компилятором.
T4 используется для кодогенерации многими проектами, начиная с Entity Framework. Вот здесь ещё достаточно впечатляющий список. Вот, например, пример того, как автоматически генерировать определения Dependency Property. (Я тоже использовал T4 для генерации из текстового представления XAML-словарей для локализации.)

Кодогенерация времени выполнения и правда не лучший метод использования T4. Для этих целей лучше подходит CodeDOM (или, кажется, Roslyn API). А для кодогенерации времени компиляции доступ к сгенерированным исходникам очень важен, например, для отладки.

Дополнение к вопросу из комментария. Да, можно в шаблоне генерировать другой шаблон.
Например, такой вот шаблон
<#@ template debug="false" hostspecific="false" language="C#" #> <#@ assembly name="System.Core" #> <#@ import namespace="System.Linq" #> <#@ import namespace="System.Text" #> <#@ import namespace="System.Collections.Generic" #> <#@ output extension=".tt" #>
<# string open = "<" + "#" + "@", close = "#" + ">"; #>
<#= open #> template debug="false" hostspecific="false" language="C#" <#= close #> <#= open #> assembly name="System.Core" <#= close #> <#= open #> import namespace="System.Linq" <#= close #> <#= open #> import namespace="System.Text" <#= close #> <#= open #> import namespace="System.Collections.Generic" <#= close #> <#= open #> output extension=".cs" <#= close #>
class Test { public int i; }
порождает подчинённый шаблон
<#@ template debug="false" hostspecific="false" language="C#" #> <#@ assembly name="System.Core" #> <#@ import namespace="System.Linq" #> <#@ import namespace="System.Text" #> <#@ import namespace="System.Collections.Generic" #> <#@ output extension=".cs" #>
class Test { public int i; }
который в свою очередь порождает класс
class Test { public int i; }
Никаких специальных действий выполнять не нужно, просто добавьте шаблон T4 через Add → New item → Text Template (не Runtime Text Template!)

В T4-файл положите текст шаблона, как он представлен выше, и вы получите такую вот необычную структуру вашего solution'а:

Python len() и .__len__() в чем разница?

В чем разница между len() и .__len__()? И могут ли они возвращать разные значения?


Ответ

__len__ это магический метод, который реализует len операцию. Как и любой другой специальный метод, он вызывается специальным образом (должен быть определён в самом классе), то есть len(o) не всегда эквивалентно o.__len__(). Подробнее в ответе о магических методах
Дополнительно, значения len() ограничены sys.maxsize
>>> import sys >>> class Big: ... def __len__(self): ... return sys.maxsize + 1 ... >>> len(Big()) Traceback (most recent call last) ... OverflowError: cannot fit 'int' into an index-sized integer >>> Big().__len__() 9223372036854775808
На практике, иногда полезно иметь последовательность с большой длиной:
Get the highest possible gmtime for any architecture Weighted random sample in python

Как правильно реализовать тестовое задание на должность PHP developer?

HR менеджер дал тестовое задание. Я выполнил. В ответ он сказал, что
я получил только краткий фидбек - не понравилось качество и стиль реализации.
Хочу вашего совета, что я не так написал. Вот задание:
Тестовое задание #1:
Версии ПО: PHP 5.3-5.6
Необходимо реализовать функцию, которая произведет чтение данных файла и вернет обработанные данные в указанном виде.
Функция должна: - Считать данные с файла - Разбить данные по строкам в массив - Отфильтровать массив таким образом, чтобы в нем остались лишь строки содержащие только числа - Суммировать числа в каждой строке - Отсортировать полученные суммы в порядке убывания - Вернуть результат
Пример кода:
# Путь к файлу данных $file = __DIR__ . '/datalist.txt'; # Передаем данные в функцию и получаем результат $result = getResult( $file ); # Отображаем результат echo '

'; 
     var_export( $result );
function getResult ( $file ) { # @TODO Реализовать... }
Пример результата работы функции: array ( 82 => 16396, 19 => 16169, 71 => 15864, 73 => 15224, 81 => 14244 ...
Кусок файла datalist.txt:
55 NTfy 591 405 kLj 48 644 768 164 ubd 837 oTft GPQV 163 ja 445 961 431 574 168 375 380 427 670 610 284 765 48 687 660 377 333 914 70 146 328 301 925 266 620 237 137 584 427 308 939 660 917 59 864 j hHo 279 tqpg 617 870 CoNJ 173 czgW 301 299 134 820 625 U 369 165 hutPN jiq 31 575 46 NS 397 378 954 764
Как я это реализовал:
# Путь к файлу данных $file = __DIR__ . '/datalist.txt'; # Передаем данные в функцию и получаем результат $result = getResult($file); # Отображаем результат echo '
';
var_export($result);
function getResult($file) { #Считать данные с файла. #Разбить данные по строкам в массив $line = file($file); $i = 0; foreach ($line as $value) { $ArrayLine = explode(' ', $value); foreach ($ArrayLine as $Record) { $result[$i] = 0; #Отфильтровать массив таким образом, чтобы в нем остались лишь строки содержащие только числа $CheckString = preg_replace('~[^A-Za-z]+~', '', $Record); if (strlen($CheckString) > 0) { unset($result[$i]); break; }; $res = (int) $Record; #Суммировать числа в каждой строке $result[$i] += $res; } $i++; } #Отсортировать полученные суммы в порядке убывания arsort($result); return $result; }


Ответ

Код
/** * Функция производит чтение данных из файла и возвращает обработанные данные согласно алгоритму * - Считать данные с файла * - Разбить данные по строкам в массив * - Отфильтровать массив таким образом, чтобы в нем остались лишь строки содержащие только числа * - Суммировать числа в каждой строке * - Отсортировать полученные суммы в порядке убывания * - Вернуть результат * * @param string $file * @return array */ function getResult($file) { $numbers = [];
$handle = @fopen($file, 'r'); if ($handle) { // Читаем файл построчно while (($buffer = fgets($handle, 4096)) !== false) { // Удаляет пробелы (или другие символы) из начала и конца строки $buffer = trim($buffer);
if (preg_match('/^[\d ]+$/', $buffer)) { // Разбиваем строку на числа, складываем получившийся массив чисел и записываем в массив $numbers[] = array_sum(explode(' ', $buffer)); } } }
// Сортируем массив по возрастанию (без сохранения отношений с ключами) rsort($numbers);
return $numbers; }
$result = getResult(__DIR__ . '/datalist.txt');
print_r($result);
Комментарии к коду:
По входному файлу, в примере, делаю следующий вывод. Функция разработана с учетом того, что числа только положительные и целые, и внутри слов нету чисел, например, oT89ft. И число не может идти рядом со словом, например, 200NTfy (то есть будет ли он считаться числом после удаление «нечисел»). Хоть в алгоритме указан шаг Разбить данные по строкам в массив, он пропускается, чтобы не «забивать» память (не происходило переполнение памяти). Потом что строк в файле может быть очень много. Чтение происходит построчно и в массив сразу вычисляется и записывается сумма. Длина строки при чтении ограничена length - 1 байт Не стал «доходить по паранойи»: сортирую массив встроенной в PHP функцией и не стал делать какой-нибудь composer-пакет с тестами. Комментарии на русском... Желательно на англ. писать, если компании не против, где работать будете — потом пригодится :)
Дополнительная информация
При написании (форматировании кода) я стараюсь следовать PHP Standards Recommendations, в частности:
PSR-1: Basic Coding Standard PSR-2: Coding Style Guide
Изучите информацию на сайте — пригодится.
И всегда обращайтесь и изучайте информацию по PHP на официальном сайте. Документация на русск. или англ. языках.
И не бойтесь ошибаться! Задавать любые вопросы на Stack Overflow!

c# результат быстрейшего потока

Как в переменную записать результат быстрейшего метода(два раза вызывается один метод с разными передаваемыми значениями, нужен результат быстрейшего метода)?


Ответ

Судя по метке, метод у вас асинхронный. В таком случае можно воспользоваться Task.WhenAny()
public async Task FooAsync(int x) { //... }
...
var task1 = FooAsync(1); var task2 = FooAsync(2); var fastestTask = await Task.WhenAny(task1, task2); var result = fastestTask.Result;
Однако может так случиться, что какой-либо таск завершится быстрее из-за исключения. В таком случае нужно снова вызвать Task.WhenAny() для оставших тасков. В общем случае решение может выглядеть так:
var task1 = FooAsync(1); var task2 = FooAsync(2); var task3 = FooAsync(3); var tasks = new List>() { task1, task2, task3 }; int result; while (tasks.Count > 0) { var fastestTask = await Task.WhenAny(tasks); if (fastestTask.IsCompleted) { result = fastestTask.Result; break; } else // если таск упал или был отменен { tasks.Remove(fastestTask); } }
Ждать или отменять оставшиеся таски, если один из них упал -- зависит от задачи. Например, если вы хотите получить цену одной и той же акции из нескольких источников, то даже если один из источников недоступен, вы дождетесь ответа другого источника. В случае если вы хотите получить цену разных акций из одного и того же источника, то, вероятно, имеет смысл отменить оставшиеся таски, поскольку понятно, что если источник недоступен, то остальные задачи тоже упадут.

Вывод результата побитовой операции в Bash

Хочу реализовать простейший пример. Есть два числа в двоичной системе 0011 и 0101. Хочу применить к ним операцию "ПОБИТОВОЕ ИЛИ". Результат вывести в виде двоичного числа. Должно получиться 0111, получаю 73. Почему так?
#!/bin/bash AA=0011 BB=0101 CC=$(($AA | $BB)) echo "Result: " $CC


Ответ

Двоичные числа в bash задаются как 2#число. Выводить в двоичном виде результат bash не умеет, можно воспользоваться bc
#!/bin/bash AA=2#0011 BB=2#0101 CC=$(($AA | $BB)) echo -n "Result: " printf "%04d" `echo "obase=2;$CC" | bc`