• Найти максимальное и минимальное значение от деления нацело?

    @Mercury13
    Программист на «си с крестами» и не только
    UPD. Переписал с нуля.
    r <= z/x < r + 1
    l <= z/y < l + 1

    Тогда y/x = z/x : z/y > r / (l+1)
    С другой стороны: y/x < z/x : z/y < (r+1)/l

    Пока вижу диапазон [r / (l+1)]; [(r+1)/l]
    Второе — минус один, если точное целое: приблизиться-то можно, а достичь нельзя. Сымитируем это таким образом…
    [r / (l+1)]; [r/l]

    Покажем, что границы достижимы (например, первая). Она затрагивает два неравенства.
    z/x < r + 1
    z/y >= l
    Подбором x, y и z можно довести второе до равенства и сколь угодно сильно приблизить первое.

    UPD2. Пусть r = [z/x] = 10, l = [z/y] = 3
    Тогда [y/x] будет в пределах от [10/4] = 2 до [10/3] = 3. А Если без целой части — то от 2,5 до 3 2/3.
    z = 100.000, x=10.000, y=25.001, y/x = 2,5001
    z = 100.000, x = 9091, y=33.333, y/x ≈ 3,66659
    Ответ написан
    Комментировать
  • Как быстро проверить правильная ли скобочная последовательность?

    @Mercury13
    Программист на «си с крестами» и не только
    Критерий таков.
    1. Баланс ( и ) должен сохраниться.
    2. а) Либо вырожденный случай (скобку меняем дважды на противоположную);
    б) либо ) → ( идёт перед ( → );
    в) либо уровень вложенности обеих скобок не менее 3, при этом они сидят в общих скобках 2-го уровня.

    Из-за 2в без предобработки за O(n) проверить невозможно. Но предобработка хороша, если мы решаем кучу таких запросов, и с этим отдельный вопрос. В таком случае, вероятно, лучше использовать дерево отрезков, обрабатывающее каждый запрос за log n. Пока мне алгоритм понятен не до конца; если вы скажете, что действительно задача про кучу запросов — подумаю..
    Ответ написан
    Комментировать
  • Какую функцию использовать для построения такого графика?

    @Mercury13
    Программист на «си с крестами» и не только
    Вариантов много. Считаем пока, что никаких требований к f(0) нет. Перемасштабируем наши переменные:
    x' = (x − 1)/9
    y = 8y' + 2.
    Тогда x' и y' будут от 0 до 1, в то время как x и y — 1…10 и 2…10. И тогда варианты.
    1. Степенная функция: y' = x'a, a = 0…1. Если a=½, то квадратный корень, ⅓ — кубический корень…
    2. Четвертушка эллипса: y' = sqrt(1 − x'²)
    3. Синус: y' = sin((pi/2)·x')

    Если же f(0) = 0, то масштабируем по-другому:
    x' = x/10
    y = 10y'
    Ответ написан
    4 комментария
  • Есть ли игры в открытом мире с круглой землей (картой)?

    @Mercury13
    Программист на «си с крестами» и не только
    В первую очередь авиасимуляторы. Знаю, что из-за масштабов Земли им приходится справляться с ошибками float: если Земля 12000 км в поперечнике, то единица младшего разряда — полметра.
    Первый X-COM имел круглую землю, но полёты были по локсодроме. А вот в опенсорсном ремейке 2014 года полёты уже по большому кругу.
    Симуляторы бога от Питера Молиньё: Populous, Black and White. Возможно, и другие симуляторы богов (например, Spore — не проверял).

    Я говорю именно про шарообразную карту, а не трубу/тор.

    А так — я бы предостерёг от шарообразной земли с открытым миром. 1) Расстояния (глобальная карта с ускоренным временем или без времени не в счёт). 2) Навигация по миру (в том числе понятие «север»), проекция миникарты. 3) В какой-то момент нужно закругляться и выкатывать игру, а в какой-то — выдавать аддон. Тяжеловато будет. Кстати, во всех упомянутых играх мир или замкнутый, или намного больше, чем одна планета.

    P.S. Моё определение открытого мира: игра, дающая относительную свободу действий и передвижения, но локальный участок, где орудует игрок/группа, намного меньше мира. В замкнутом мире, наоборот, участник орудует практически по всему «миру», оперативно переходя с одного участка на другой. Есть и пограничные случаи: огромное побережье нового Hitman — открытый мир или замкнутый?
    Ответ написан
    1 комментарий
  • Почему в ряде Тейлора есть факториал и выражение в скобках имеет степень?

    @Mercury13
    Программист на «си с крестами» и не только
    Самый прикол ряда Тейлора — почему у него такой остаточный член.
    У Лагранжа и Коши
    Члены очень хороши.
    А у Шлёмильха и Роша
    Самый, говорят, хороший.

    Решим задачу попроще: прикинем на пальцах форму степенного ряда Sum{aixi}, который приближает функцию в окрестности x=0.
    0-е приближение: f(x) ≈ f(0).
    1-е приближение: f(x) ≈ f(0) + f'(0)·x.

    Пока никаких нареканий. Подумаем над вторым приближением.
    f(x) ≈ f(0) + f'(0)·x + ax².
    Хотелось бы, чтобы этот многочлен имел такие же производные вплоть до второй, как и функция f. (x²)|x=0=(x²)'|x=0=0, с этим никаких проблем. Поскольку (x²)''|x=0=2, получается, что a=f''(0)/2.

    И сразу n-е приближение.
    f(x) ≈ f(0) + f'(0)·x + f''(0)·x²/2 + … + bxn.
    И этот многочлен должен иметь такую же n-ю производную, как и функция f. Чему равен (xn)(n)|x=0? Разумеется, n!. Отсюда и коэффициент f(n)(0)/n!.
    Ответ написан
    1 комментарий
  • Языки программирования для работы с API?

    @Mercury13
    Программист на «си с крестами» и не только
    Любой, работающий с HTTP.
    Привязки к cURL — а именно он в большинстве случаев используется для HTTP — есть практически везде.
    Проверено: есть сайты, где Indy (стандартная сетевая библиотека Delphi) не пройдёт, а cURL — за милую душу. Видимо, криптография + «Indy слишком вумный и скрытно корректирует сообщение».
    Ответ написан
    Комментировать
  • Структура данных типа очереди, позволяющая быстро определить позицию элемента. Есть?

    @Mercury13
    Программист на «си с крестами» и не только
    Очередь, физически не перемещающая элементы (кольцевая или некое подобие std::deque) и позволяющая по указателю быстро определить позицию.

    Плюс любой индекс (хэш- или деревянный), элементы которого — указатели на элементы очереди. Если элементы очереди unique_ptr, то указатели будут именно на unique_ptr! Для «мусорных» языков (C#, Java) вместо указателей можно придумать какие-то идентификационные коды — например, сочетание из номера в пуле массивов и номера в массиве.

    Enqueue — вписываем элемент в индекс. Dequeue — удаляем из индекса. Обмен позициями — корректируем эти два элемента индекса.
    Ответ написан
    Комментировать
  • Почему на 4-х ядерном процессоре происходит эмуляция 12-и ядерного?

    @Mercury13
    Программист на «си с крестами» и не только
    1. Такую работу со счётчиком threadEnd лучше делать через std::atomic.
    2. В вашем процессоре два гипертредированных ядра, 4 потока.
    3. Главный поток ждёт-крутится. «1 поток» — это работают ДВА потока (не забывайте, главный просто крутится). «2 потока» — это ТРИ потока, два настоящих ядра и одно виртуальное — потому результаты не вдвое ниже. Так что вижу локальный минимум на трёх потоках, это верно. У меня на рабочем 8-поточном процессоре, как и полагается, даёт минимум на семи потоках.
    4. Условие if (natur > 0) кажется излишним.
    5. Вижу большой разброс результатов. То ли таймер недостаточно точный, то ли компьютер загружен кучей посторонней работы — таким результатам доверять не стоит.
    Ответ написан
    2 комментария
  • Как решить эту задачу со множествами?

    @Mercury13
    Программист на «си с крестами» и не только
    1. ВЕРНО. A \cap C \in A \in B \in B \cup D (прости уж, что пишу тэгами TeX).
    3. ВЕРНО, следует из законов логики.
    5. UPD. Всё-таки ВЕРНО, тут надо действовать через x. Пусть $x \in A \cap C$, тогда $x \in A$ и $x \in C$. А значит, $x \in B$ и $x \in D$. Дальше понятно? Точно так же можно решить и 3.
    Ответ написан
  • Почему в интерфейсе могут быть только public методы?

    @Mercury13
    Программист на «си с крестами» и не только
    Private — на что? Ведь тот, кто пойдёт этот интерфейс реализовать, их не увидит.

    С protected штука более сложная. Дело в том, что в классическом интерфейсе ноль кода и данных, и эти protected должен вызывать — кто — разумеется, потомки. Преждевременно увековечивать внутреннюю архитектуру — зачем?

    Встречается ещё такая штука, как «прокачанный интерфейс» — не знаю, как он правильно называется по ООП. Там есть две новых вещи: 1) утилиты — невиртуальные функции, которые представляют собой стандартный сценарий пользования интерфейсом; 2) штатные реализации — некоторым виртуальным функциям придумывают реализацию, которая как-то работает и пользуется другими виртуальными, но потомок, если захочет, может написать более эффективную версию.

    Вот например, утилита.
    // write Intel word
    void st::Stream::writeIW(uint16_t w)
    {
        write(&w, sizeof(uint16_t));
    }
    Утилита не часть интерфейса, и лучший синтаксис для утилит — методы-расширители C#. На худой конец подойдёт простая функция типа Streams.writeIW(stream, 10);.

    Вот, например, штатная реализация.
    // Возвращает остаток потока
    // cu_minus = clipped unsigned minus
    virtual Pos remainder() { return cu_minus<Pos>(size(),pos()); }
    Если в языке нет штатных реализаций, строят класс, где эти функции чем-то реализованы — не всегда, но часто можно унаследоваться от этого класса.

    Раз утилита пользуется обычными общедоступными функциями, нет никакого смысла её кидать в protected (теоретически private/protected могут быть некоторые части сложных утилит). Штатные реализации — тем более, это такая же часть интерфейса, как абстрактные size() и pos().
    Ответ написан
    Комментировать
  • Робот художник. Как перевести растровую картинку в набор функций?

    @Mercury13
    Программист на «си с крестами» и не только
    Ищите по ключевым словам «image tracing». Inkscape, допустим, использует открытую программу PoTrace.
    Ответ написан
    1 комментарий
  • Как найти координаты точки?

    @Mercury13
    Программист на «си с крестами» и не только
    Я плохо понял, что надо сделать. Но попробую.
    1. Переведи известный катет в вектор: (X3−X1, Y3−Y1).
    2. Поверни его на 90° в нужную сторону. Например, x'=y, y'=−x.
    3. Приведи к нужной длине (теорема Пифагора). Получился вектор-катет.
    4. Прибавив вектор-катет к вершине (X1, Y1), получаем второй конец.
    Ответ написан
    Комментировать
  • Как получить доступ к полям и методам неизвестного объекта?

    @Mercury13
    Программист на «си с крестами» и не только
    Это значит: объект класса B должен иметь (или не иметь) «товарища» класса C. Иметь не во владении, а по ссылке. А лучше не класса C, а его подмножества, реализованного как интерфейс (я его назвал IC). На A вообще чхаем — его задача собрать B и C в нужном виде, и всё.

    Смотрите шаблон проектирования Dependency Injection.

    class IC {   // interface
    public:
      virtual int getC() = 0;
      virtual ~IC() = default;
    };
    
    class C : public IC {
    public:
      int getC() final { return 42; }
    };
    
    class B {
    public:
      IC* buddy() const { return fBuddy; }
      void setBuddy(IC* aBuddy) { fBuddy = aBuddy; }
      void someJob() const { if (fBuddy) std::cout << fBuddy->getC() << std::endl; }
    private:
      IC* fBuddy = nullptr;
    };
    
    class A {
    public:
      A() { b.setBuddy(&c); }
    private:
      C c;
      B b;
    }

    Специально для тех, кто на Си++: в таком виде A неперемещаем из-за указателя c.fBuddy. Есть много способов исправить это — например, подправить конструктор копирования и операцию «присвоить» класса A.
    Ответ написан
    3 комментария
  • В чем проблема??

    @Mercury13
    Программист на «си с крестами» и не только
    Если упустить знак & вместо &&, в вашем коде три проблемы.
    1. Часть сравнений излишни: например, из тройки a >= b && a >= c && c <= b второе не нужно. Можно просто писать: c <= b && b <= a.
    2. Часть сравнений повторяется. Лучше было бы работать
    if (a >= b) {
       // куча сравнений
    } else {
       // ещё одна куча
    }

    3, самое главное. Может случиться, что ни одна ветка не сработает, и в переменных будет мусор! Непонятно, какова задача, так что не могу сказать, как исправить. Если независимо друг от друга отсортировать две тройки — зачем вы всё это делаете одним оператором?
    Ответ написан
    Комментировать
  • Как изменить формат данных передаваемых из Excel?

    @Mercury13
    Программист на «си с крестами» и не только
    Плавали, знаем. В массив поступает как раз то, что нужно. Причина в алгоритмах конвертации число→строка, и надо добавить такую штуку:
    «Если число — по типу Double, по факту точное целое и находится в определённых пределах, преобразовать его в Int64, а затем Int64 в строку».

    Сама проверка, является ли double точным целым, довольно сложна. У меня есть код для этого на Си++ (который, в свою очередь, является портом кода из Java). Портанёте на Delphi сами?

    enum {
        DOUBLE_MANTISSA_BITS = 52,
        DOUBLE_MIN_EXPONENT = -1022,
        DOUBLE_EXPONENT_BIAS = 1023,
    };
    
    #define UC8x(X,Y,Z,T) (static_cast<uint64_t>(0x##X##Y##Z##T##ULL))
    #define DOUBLE_MANTISSA_MASK     UC8x(000f, ffff, ffff, ffff)
    #define DOUBLE_EXPONENT_MASK     UC8x(7ff0, 0000, 0000, 0000)
    #define DOUBLE_EXPONENT_MASK_HI  UC4x(7ff0, 0000)
    #define DOUBLE_IMPLICIT_BIT (DOUBLE_MANTISSA_MASK + 1)
    
        union DoubleInt {
            double asDouble;
            uint64_t asInt;
            struct {
                uint32_t lo, hi;
            } asIntel;
        ....
       }
    
        int DoubleInt::exponent() const
        {
            return static_cast<int>((
                          static_cast<int64_t>(asInt & DOUBLE_EXPONENT_MASK) >>
                          (DOUBLE_MANTISSA_BITS)) - DOUBLE_EXPONENT_BIAS);
        }
    
        uint64_t DoubleInt::unsafeMantissa() const
        {
            int ex = exponent();
            uint64_t bits = asInt & DOUBLE_MANTISSA_MASK;
            return (ex == DOUBLE_MIN_EXPONENT - 1)
              ? bits << 1
              : bits | DOUBLE_IMPLICIT_BIT;
        }
    
        bool DoubleInt::isPreciseInteger() const
        {
            // функцию isFinite() намеренно упустил, ибо она есть «в коробке» Delphi.
            // А вот в Си++ есть не во всех реализациях…
            return isFinite()
                && (asDouble == 0.0 ||
                DOUBLE_MANTISSA_BITS - numberOfTrailingZeros(unsafeMantissa()) <= exponent());
        }
    
    int math::numberOfTrailingZeros(uint64_t i)
    {
        uint32_t x, y;
        if (i == 0u) return 64;
        int n = 63;
        y = static_cast<uint32_t>(i);
        if (y != 0) { n = n -32; x = y; } else x = (int)(i >> 32);
        y = x << 16; if (y != 0) { n = n -16; x = y; }
        y = x << 8;  if (y != 0) { n = n - 8; x = y; }
        y = x << 4;  if (y != 0) { n = n - 4; x = y; }
        y = x << 2;  if (y != 0) { n = n - 2; x = y; }
        return n - ((x << 1) >> 31);
    }
    
    bool math::isPreciseInteger(double x)
    {
        DoubleInt di;
        di.asDouble = x;
        return di.isPreciseInteger();
    }


    Может быть, вам сработают и упрощённые варианты вроде «столбец X — преобразовать в Int64, затем в целое». В промышленной программе этого не хватало.
    Ответ написан
    Комментировать
  • Зачем нужна перезагрузка роутера?

    @Mercury13
    Программист на «си с крестами» и не только
    1. Процессор заглючил из-за случайного сбоя: из-за сбоя по питанию, или из-за космической частицы. Такое по-чёрному бывает в космических аппаратах — вот только не перезагрузишь процессор, когда он в тысячах км от тебя. Когда под столом — другое дело.
    2. Ошибка в программе, чреватая вылетом или утечкой памяти (в первом случае программа останавливается, во втором — потребление памяти повышается, пока не съест всю доступную память). Если устройство без операционной системы, сбой программы приводит к полной остановке устройства, если с ОС — к остановке или перезапуску какого-нибудь процесса, что чревато полной или частичной потерей функциональности.
    3. Фрагментация памяти при большом аптайме. Обычно случается при постоянном хаотичном выделении-освобождении.

    Конкретно в маршрутизаторе — в 90% случаев дело в 2-й причине (реже в 1-й или 3-й).
    Ответ написан
    4 комментария
  • Как используются константы и кастинги?

    @Mercury13
    Программист на «си с крестами» и не только
    В Си++03 константа — это та же переменная, про которую говорится: её нельзя менять, с одним дополнением.
    Если эта переменная ещё и целая, при определённых условиях её значение вычисляется при компиляции и может использоваться, например, в шаблонах или массивах.

    В Си++11 понятия «нельзя менять» и «вычисляется при компиляции» разделили, добавив ключевое слово constexpr.

    Для чего?
    1. Обозвать число. Например, 3,1416 — это пи, −128 — минимум signed char, а 16384 — ёмкость промежуточного буфера.
    2. Наладить какую-нибудь таблицу данных, которую нельзя менять.
    const int FIBONACCI_TABLE[] = { 0, 1, 1, 2, 3, 5, 8, 13 };

    3. Сказать: эта переменная передана по указателю/ссылке, но мы её менять не будем.
    void sayHello(const std::string& name);
    void sayHello(const char* name);


    О преобразовании типов. Если мы подали в какую-нибудь операцию или функцию слегка не тот тип, какой хотели, компилятор способен наладить преобразование.
    float oneAndHalf = 1.5f;
    int one = oneAndHalf; // 1

    Это и есть неявное преобразование типа. В данном случае вредное :)

    Явное преобразование типа нужно, когда неявное не прокатывает. А именно…
    • Компилятор не понимает, какую использовать перегрузку.
    • При сравнении знакового числа с беззнаковым — это сравнение можно проводить в знаковом типе, в беззнаковом или в более широком. Не ошибка, но предупреждение.
    • Программист запретил неявное преобразование ключевым словом explicit.
    • Нужна цепочка из двух преобразований типа.

    Явное преобразование бывает тремя способами: вызов конструктора int(1.5), преобразование как в Си (int)1.5 и ключевое слово static_cast static_cast<int>(1.5).
    Ответ написан
  • Правда ли, что критическом перегреве видеокарты ноута, она потом всегда будет греться?

    @Mercury13
    Программист на «си с крестами» и не только
    В некоторых видяхах бывает отвал крышки. Симптомы те же: перегрев даже без нагрузки.
    Ремонт подобной видяхи видал на YouTube на канале «CoRE: Center of Repair Engineering».
    Дело противное, долгое и негарантированное. Многим проще припаять новый видеочип.

    UPD. Дома нашёл видео. https://www.youtube.com/watch?v=044CyNRR2FE
    И ещё одно: https://www.youtube.com/watch?v=ghUwOSyHHJ8
    Ответ написан
    Комментировать
  • Как вставить значение строки как аргумент функции?

    @Mercury13
    Программист на «си с крестами» и не только
    1. В строковой переменной или строковом буфере собрать тело команды, экранируя параметры, если это нужно.
    2. Если это обёрнутый string, преобразовать в const char* — и пошёл.
    std::string command;
    char data1 = 'F';
    char data2 = 'C';
    command = std::string("color ") + data1 + data2;
    system(command.c_str());
    Ответ написан
    1 комментарий
  • Почему не компилируется код на С (gcc)?

    @Mercury13
    Программист на «си с крестами» и не только
    Я бы пенял на ложную тревогу антивируса.

    Кроме того, программа неверна. В ней card_name используется раньше, чем заполняется чем-то стóящим.
    Ответ написан