Pull to refresh
68
Евгений Красников@jin_x

Программист, вокалист, активист, оптимист.

22
Subscribers
Send message

По технологии: почему у вас одно из значений base-префикса не используется (00)? Почему бы не сделать "repeating until the value is ≤ 4"?

"Decoding Steps" — как понять, что кодирование закончилось? Встретили мы единицу: это новый блок или terminator?

01 100000000000 1 ^^ ^ K=1 терминатор Одна единица в данных → читаем до неё → готово. Число 2048 закодировано в 15 бит. В u16 оно стоило бы 16. Число 4294967296 закодировалось бы в 35 бит. В u64 стоит 64.

А вот тут совсем не понятно. Читаем до 1 единицы. Так, единица же в самом начале, почему мы должны читать ещё 11 нулей? Или у вас тут перевёрнуто?

Вам бы, конечно, несколько примеров привести. По паре штук хотя бы где только база, где +1 popcount, +2 popcount. И без опечаток.

И заодно интересно, как кодировать 0? Или мы работаем только с натуральными числами?

Да, с С/С++ кодом я немного поторопился, конечно :)

А целом компилятор sum += a <= b ? addend : 0 вполне нормально на cmovle/cmovg заменяет.

popcount = 2 → читай пока не встретишь 2 единицы

Это опечатка? Тут вроде 5.

Для условного перемещения есть cmovcc (csel в ARM). Как вариант:

setle al
movzx eax,al
neg eax
and eax,edx
add [count],eax

Но это хуже, конечно, больше зависимостей и лишних операций.

Не проверял, но надеюсь, компилятор догадается (и тут нужно переделать без UB):

sum += (a <= b ? UINT_MAX : 0) & addend;

Дружище, советую Qalculate! Несколько месяцев назад пересел на него, ибо задолбало автоматическое переключение режимов в NumLock Calculator (то 16-ричный включится, то режим Си), потом ещё запятая вместо точки. Единственный косяк — gtk-версия долго запускается. В итоге я написал мини-тулзу, которая прячет/показывает/активирует окно (могу скинуть с исходником, если надо). И в самом калькуляторе настроить клавиши переключения режимов dec-hex-bin в окнах ввода и результата. Доволен.

Ещё один классный калькулятор — Precise Calculator, но для постоянного использования не так удобен, зато быстро считает сколько угодно знаков (до и после запятой), можно использовать переменные и пр.

Это 3.143Dец! 🤦‍♂️

А из Shelter'а увидеть интерфейсы основного профиля можно?

Жесть, конечно. Я сначала даже усомнился, что Shelter реально пропускает прокси, но установил туда телегу, и она успешно подключилась через носки.

Вопрос про Amnezia. Я так понимаю, она пробрасывает SOCKS5 через порт 10808 только для Xray? А если используется AWG? Мне не удалось подключиться к телеге по этому порту. Ну и nmap -p- 127.0.0.1 ничего не выдаёт.

@runetfreedom, могли бы вы написать список приложений, которые прошли проверку и не содержат уязвимостей? Чем можно пользоваться сейчас? FlClashX тоже уязвим?

Действительно. В этой редакции этот косяк исправлен.

Только зачем тут нужен публичный конструктор?

Чтобы не тратить драгоценные байты на mov rdx,0xFFFFFFFF00000000 (целых 10 байт), можно сделать например, вот так:

mov	edx,eax  ; 2 байта
xor	rax,rdx  ; 3 байта (можно `sub`)

Ещё вариант (чуть длиннее, но без доп. регистров):

shr rax,32  ; 4 байта
shl rax,32  ; 4 байта

Ну и до кучи вариант обнуления 31 младшего бита (не 32-х):

and rax,0x80000000  ; 6 байт (тут происходит знаковое расширение константы до 64 бит)

Есть множество способов обнулись регистр, например:

xor eax,eax ; а также pxor xmm0,xmm0; xorps, xorpd, vpxor, etc...
sub eax,eax ; sbb, если cf=0
and eax,0
lea eax,[0]
push 0 / pop eax
salc ; al=0, если cf=0
cbw ; ah=0, если старший бит al=0; а также cwd, cdq, cqo
xchg eax,ebx ; ax=0, если bx=0 и наоборот; mov ax,bx аналогично
fldz ; fninit (не совсем обнуление, конечно, но как варик)
vzeroall ; vzeroupper
mov eax,eax ; старшая часть rax обнуляется
mov eax,0 ; внезапно

; странные способы (обфускация, например):
loop $ ; ecx=0; dec eax/jnz $-1 (для 32 битов); можно сделать rdtscp/inc ecx/loop $ (чтоб не гонять слишком долго)
mul ecx ; eax=edx=0, если ecx=0; аналогично fmul, fmulp, mulps, pmul...
mov ecx,-1 / div ecx ; eax=0, если edx=0; есть также divps и пр.
aad 0 ; ah=0
aam 1 ; ah=0
aam 0 ; al=0
shr ax,16 ; shr ax,cl, если cl = 16..31; можно shl
bzhi eax,eax,ecx ; если ecx=0
mov ecx,0FEh / rdmsr ; edx=0
mov eax,80000000h / cpuid ; ah=ebx=ecx=edx=0
movzx eax,al ; очищаем старшие 24 бита (56 в x64); есть ещё pmovzx
in ax,dx ; если правильно выбрать порт

; если значение ax заранее известно и очень подходит под ситуацию, можно inc eax, dec eax, not eax, lodsb, scasw, bswap и т.д.
; если знаем, что в памяти, то можно lds, les, mov eax,[ebx], pop ecx (например, на старте com-программы), xlatb, lodsw и т.д.
; по любому есть ещё 100500 способов

Иногда стоит использовать обе диаграммы, если место позволяет. Но мне часто не хватает понимания, на сколько % одно значение больше/меньшее другого. Например, сделали какой-то бенч. Получилось 90, 105, 120, 130. Хочется видеть разницу в % относительно, скажем, 120. Это редко когда пишут.

Ещё можно отдельную статью написать (мне даже кажется, что она уже была) о масштабировании диаграмм и графиков. Если мы рисуем эквалайзер, то логарифмическая шкала и плавающий низ — это ок. А вот когда какое-то значение отображается в диапазоне от 10 до 11 кривой по всей высоте (а низ тупо отрезается), то это очень мешает понимать реальное соотношение значений и глобальность измерения.

Сорян, первый сниппет на C++20 (std::string_view::starts_with).

Похоже, Дядюшке Бобу пора пить таблетки перед написанием книги :))

Повторю (перефразируя) коммент под предыдущей статьёй: в многопоточном коде, если разные потоки будут использовать один экземпляр класса, любовь к манипуляциям с переменными объекта приведёт к большим проблемам.

Не претендую на идеальность, но код из книги явно можно сделать проще и понятнее, например, так (C++17):

#include <array>
#include <string_view>
#include <optional>

std::optional<int> roman_to_int(std::string_view source)
{
    struct RomanInfo {
        std::string_view roman;
        int value;
        size_t skip = 0;
    };
    constexpr std::array<RomanInfo, 17> numbers = {{
        { "MM", 2000 }, { "M", 1000 },
        { "CM", 900, 4 }, { "D", 500 }, { "CD", 400, 2 }, { "CC", 200 }, { "C", 100 },
        { "XC", 90, 4 }, { "L", 50 }, { "XL", 40, 2 }, { "XX", 20 }, { "X", 10 },
        { "IX", 9, 4 }, { "V", 5 }, { "IV", 4, 2 }, { "II", 2 }, { "I", 1 }
    }};

    int result = 0;
    for (auto num = numbers.begin(); !source.empty() && num != numbers.end(); ++num) {
        if (source.starts_with(num->roman)) {
            result += num->value;
            source.remove_prefix(num->roman.size());
            num += num->skip;
        }
    }
    if (result == 0 || !source.empty()) { return {}; }
    return result;
}

Ну или так (unordered_map здесь не нужен, только усложнит код):

#include <string_view>
#include <optional>

std::optional<int> roman_to_int(std::string_view source)
{
    if (source.empty()) { return {}; }
    int result = 0, prev = INT_MAX, same_count = 0;
    while (!source.empty()) {
        struct { int check, add, count_limit; } value;
        switch (source.front()) {
            case 'M': value = { 100, 900, 3 }; break;
            case 'D': value = { 100, 400, 1 }; break;
            case 'C': value = { 10, 90, 3 }; break;
            case 'L': value = { 10, 40, 1 }; break;
            case 'X': value = { 1, 9, 3 }; break;
            case 'V': value = { 1, 4, 1 }; break;
            case 'I': value = { 0, 1, 3 }; break;
            default: return {};
        }
        if (value.check == prev) {
            value.add -= value.check;
            prev = value.check - 2;  // CM/CD: prev = 98 | XC/XL: prev = 8 | IX/IV: prev = -1
        } else {
            value.add += value.check;
            if (value.add < prev) {
                same_count = 1;
            } else if (value.add > prev || ++same_count > value.count_limit) {
                return {};
            }
            prev = value.add;
        }
        result += value.add;
        source.remove_prefix(1);
    }
    return result;
}

Мысль убрать else, конечно, хорошая, но глобально это не повлияет на результат. Оптимизатор всё равно уберёт else (и даже если отключить оптимизацию, то может быть будет лишний прыжок после return, который всё равно недостижим). При этом какой код читабельнее — вопрос спорный.

Я бы ещё добавил тот факт, что если вдруг кто-то захочет использовать один экземпляр такого чудесного класса дядюшки Боба в нескольких потоках, его ждёт сюрприз :)

P.S. Да, книжка вызвала много вопросов и сомнений.

private String formatCountSentence(char letter, int count) {
    if (count <= 1) {
        if (count == 1) {
            return String.format("There is 1 %s", letter);
        }
        return String.format("There are no %ss", letter);
    }
    return String.format("There are %d %ss", count, letter);
}

Меньше ветвлений для значений > 1, отрицательное значение обрабатывается как ноль (это можно сделать контрактом).

Когда налог на бороду уже введут? Или пока рановато?

1
23 ...

Information

Rating
6,846-th
Location
Самара, Самарская обл., Россия
Date of birth
Registered
Activity

Specialization

Десктоп разработчик, Бэкенд разработчик
C++
Assembler
Системное программирование
Разработка программного обеспечения
Многопоточность
Delphi
C