• Как лучше задать табличную функцию с редкой областью определения?

    @Mercury13
    Программист на «си с крестами» и не только
    Если аргументы до 100, функция заранее известна и неизменна — чхайте на всё и делайте простым массивом. Именно так, таблицей переходов, внутри устроен switch. Всё, что я пишу ниже — для общего развития.

    Это называется «разреженный массив» (sparse array)

    1. Хэш-таблица (std::unordered_map).
    Преимущество: есть «в коробке», очень быстра.
    Недостаток: ест много памяти.

    2. Я также использую вот такой механизм.
    template <class T>
    class ChunkMap
    {
    public:
        // Data access
        //------------------------------------------------------------------------//
        /// @return  data at index t, or empty value
        T get(size_t t) const;
    
        //------------------------------------------------------------------------//
        /// Sets data at index t (empty value to erase)
        void put(size_t t, T x);
    
        //------------------------------------------------------------------------//
        /// Erases range [0..maxPlus)
        void eraseTo(size_t aMaxPlus);
    
        // Info
        size_t nChunks() const { return fChunks.size(); }
        bool isEmpty() const { return fChunks.empty(); }
    
        //------------------------------------------------------------------------//
        /// @return  the number that is beyond all chunks
        size_t ceil() const;
    
        //------------------------------------------------------------------------//
        /// @return  actual number of records in the map
        size_t size() const;
    
        //------------------------------------------------------------------------//
        /// @return  lowest value in the map; (0, empty) if empty
        std::pair<size_t, T> lowerValue() const;
    
        //------------------------------------------------------------------------//
        /// @return  highest value in the map; (0, empty) if empty
        std::pair<size_t, T> upperValue() const;
    
        //------------------------------------------------------------------------//
        /// @return  (t1, v), t1 <= t;  (0, empty) if none
        std::pair<size_t, T> lowerOrEq(size_t t) const;
    
        template <class Body> void loop(const Body& r) const;
        template <class Body> void loopFrom(size_t aMin, const Body& r) const;
    
        //------------------------------------------------------------------------//
        ///  Loops all data. Body is bool-convertible.
        ///  Return true → go on.
        ///  Return false → stop and return false.
        template <class Body> bool loopBool(const Body& r) const;
    
        void clear() { fChunks.clear(); }
    
        constexpr static T emptyValue() { return std::numeric_limits<T>::max(); }
        static bool isEmptyValue(const T& x) { return (x == emptyValue()); }
    
        constexpr static unsigned chunkSize() { return Chunk::SIZE; }
    
    private:
        struct Chunk
        {
            enum { SIZE = 8 };
            Fix1d<T, SIZE> data;   // мой шаблон, массив фиксированного размера с проверкой на выход за границы
    
            Chunk();
            bool isEmpty() const;
            std::pair<size_t, T> lowerValue(size_t aKey) const;
            std::pair<size_t, T> upperValue(size_t aKey) const;
        };
        typedef std::map<size_t, Chunk> Chunks;
        Chunks fChunks;
    };

    Можно делать и на unordered_map при желании, но мне нужна lowerOrEq().

    Преимущество: экономия памяти, если есть несколько значений рядом.
    Недостаток: больше расход памяти (ненамного).

    3. Вот ещё есть реализация на Java.
    https://android.googlesource.com/platform/framewor...
    Преимущество: серьёзная экономия памяти.
    Недостатки: когда массив велик (тысячи заполненных элементов), снижается скорость доступа. Большие расходы на чистку мусора.
    Ответ написан
    Комментировать
  • Как оценить работу функции которая рассчитывает вероятность наступления события?

    @Mercury13
    Программист на «си с крестами» и не только
    Тогда возникает вопрос. Какие могут быть недостатки у функции?

    1. Смещение к «да» или смещение к «нет».
    Для всех случившихся событий перемножаем вероятности соотв. исхода. То же самое для всех неслучившихся. Одно делим на другое, в идеале должна получиться единица.
    Можно работать с логарифмами, даже очень широкая статистика не даст переполнения: на мантиссу в double шесть байтов, а на порядок — и двух нет. Можно проводить сброс порядка: получили, скажем, число меньше 1e−50 — множим на эту цифру, запоминаем: 50 порядков в уме.
    Если статистики очень много, стоит кластеризовать входы и для каждого кластера посчитать эту статистику.

    2. Излишняя самоуверенность. Функция говорит «0,9», в то время как вероятность максимум 0,7. Думаю, можно решить той самой кластеризацией по выходу функции.

    3. Неуверенная работа. Функция не даёт статистических аномалий, но просто неуверенно работает, слишком часто выдавая «а хрѣнъ его знает». Vlad_Fedorenko предлагает площадь под ROC-кривой. Я бы просто предложил произведение вероятностей соответствующих исходов. Например, если у нас 6 пусков, можно сказать: «вероятность всегда 0,5», и получить результат 1/64≈0,016. А можно сказать: для трёх пусков вероятность 2/3, и для трёх — 1/3. Если так и случится, результат — 24/36≈0,022. Какой будет нормирующий коэффициент, сказать пока не могу.
    UPD3. А ещё можно попробовать информационную энтропию.
    UPD4. Эта конструкция, возможно, справится и с излишней самоуверенностью. Если она скажем этим тройкам 0,9 и 0,1, будет (0,9·0,9·0,1)² < 0,01.
    UPD5. Идеал — разумеется, 1 (событию говорит 100%, если оно будет, и 0%, если нет).

    UPD. Подкорректировал 1 — я так и имел в виду, но проглючил.
    UPD2. Добавил неуверенную работу.
    Ответ написан
    Комментировать
  • Как изменить присвоенное значение переменной char?

    @Mercury13
    Программист на «си с крестами» и не только
    В Си нет даже строкового типа. Вся работа со строками идёт на самом низком уровне.

    Строка 9.
    1. Использовать if (strcmp(string_1, "0") == 0).
    2. Тело if сейчас пустое, убрать точку с запятой. А лучше — использовать фигурные скобки.

    Строка 10.
    1. Выход за границы диапазона.
    2. Если заменить 7 на 6, то в модели строк Си ничего не делает — если строка состоит из нуля, NUL и пяти символов мусора, то что ни пиши в мусор, значение не изменится.
    3. Если надо присвоить завершающий NUL — используй '\0'.
    4. Если хочешь просто присвоить строке значение «00», используй strcpy/strncpy.
    Ответ написан
    Комментировать
  • Как разделить два числа в Assembler при помощи цикла?

    @Mercury13
    Программист на «си с крестами» и не только
    Хотелось бы уточнить.
    1. Размеры делимого и делителя.
    2. Знаковые или беззнаковые?
    3. Нужен ли остаток?
    4. Делим на константу или на что-то заранее неизвестное?

    Вот для примера 16-битное беззнаковое делить на произвольное 8-битное беззнаковое, как я понял, без остатка.
    www.avr-asm-tutorial.net/avr_en/calc/DIV8E.html

    А вот так работает деление на константу (в данном случае на 6).
    stackoverflow.com/questions/34136339/how-does-divi...
    Ответ написан
  • Как посчитать угол по 2-м координатам?

    @Mercury13
    Программист на «си с крестами» и не только
    Как я понял, вам нужен угол вектора (x1,y1)→(x2,y2).
    Любой школьный «арк», если им действовать в лоб, в определённом диапазоне углов не определён или неустойчив.
    Но именно для этого в большинстве языков присутствует функция
    atan2(y2 - y1, x2 - x1)
    Ответ написан
    Комментировать
  • Как обрабатывать события в Qt?

    @Mercury13
    Программист на «си с крестами» и не только
    Вы, разумеется, орудуете встроенным в Qt Creator редактором форм…
    1. Визуально: ПКМ, Go to slot…
    Программно: функцией connect, это описал AtomKrieg.
    2. Все компоненты находятся в доп. объекте ui. Когда вы делаете форму программно, им не обязательно там быть, но редактор форм делает именно так.
    if (ui->textEdit->text() == "Hi") label->setText("Hi!");
    Ответ написан
  • Как задать програмнно отобразить поверх других форм форму вызванную через Show()?

    @Mercury13
    Программист на «си с крестами» и не только
    Комментировать
  • Передача данных по ftp. Как сделать?

    @Mercury13
    Программист на «си с крестами» и не только
    Наиболее известная штука — cURL. Помимо FTP, поддерживает FTP+TLS и SFTP.
    Вот пример для FTP-закачки.
    https://curl.haxx.se/libcurl/c/ftpupload.html

    На C++ лучше использовать «плюсовые» обёртки для cURL, но код в целом такой же.
    Ответ написан
    Комментировать
  • Что такое call stack?

    @Mercury13
    Программист на «си с крестами» и не только
    Call stack — это стек вызовов, аппаратная фишка всех крупных процессоров.

    int foo()
    {
       int y = ...;
       if (y < 0)
         y = -y;
       return y;
    }
    
    void bar()
    {
       int x = foo();
       if (x != 0)
          bar();
       foo();
    }
    
    void main()
    {
      int z = foo();
      bar();
    }


    Вот мы заходим в функцию main(). В это время в памяти появляется переменная z. А затем в foo() — появляется ещё и переменная y. А затем выходим из foo — y исчезает. Что у нас получается? Либо в конец добавляем одну или несколько локальных переменных, либо с того же конца удаляем их. Какая структура данных подходит для этого? Стек: добавлять в конец, удалять из конца. Всё это, напоминаю, реализовано в x86 аппаратно, одним сегментом, двумя регистрами (esp = 32-bit stack pointer и ebp = 32-bit base pointer) и несколькими командами (push, pop, call, ret…).

    Локальные переменные, принадлежащие одной функции, называются стековый фрейм. При этом фреймов одной функции может быть несколько, если она вызывает сама себя, прямо или опосредованно — как функция bar().

    В наиболее известной модели вызова можно, «разматывая» стек фрейм за фреймом, посмотреть, какая функция какую вызвала. Это и выведено в окне Call Stack. Поскольку отладочный доступ очень медленный, обычно выводится только верхушка стека. Более того, ткнув в любом месте окна Call Stack, мы можем увидеть локальные переменные того экземпляра функции.

    Поскольку стек аппаратный, его нельзя расширять; можно только до начала программы/потока указать, сколько памяти нам хватит. И потому часта ошибка «переполнение стека».
    Ответ написан
    Комментировать
  • Как рисовать на QPixmap?

    @Mercury13
    Программист на «си с крестами» и не только
    Ваши ошибки.
    1. QPixmap — сам по себе указатель совместного владения; если надо его ненадолго создать — делайте на стеке, никаких new!
    1.1. Аналогично и QPainter, только он указатель единоличного владения. Кстати, это однажды сыграло с одной моей программой злую шутку, когда она выжрала всю память.
    2. Зачем нужна генерация Pixmap’а в процедуре перерисовки формы? Если ваш потомок сам корректно рисует картинку — генерируйте её по событию «что-то изменилось».

    Далее, если картинок может быть конечное, но достаточно большое число (например, тысячи), можно наладить кэш, где хранятся подготовленными, например, последние двадцать. Если картинок немного (до сотни), лучше при загрузке программы подготовить их все.
    Ответ написан
    Комментировать
  • Как сделать управляемый интерфейс?

    @Mercury13
    Программист на «си с крестами» и не только
    Дело тут вот в чём. Оконные ОС работают в событийном режиме: пришло событие «перерисовать», мы рисуем; пришло событие «щёлкнуть», мы щёлкаем. Но поскольку учебным программам надо быть предельно простыми, куда удобнее написать: нарисовать, дождаться нажатия клавиши — как во времена ДОС, когда процессорное время было полностью вашим от точки входа до передачи управления, когда был прямой доступ к видеопамяти… Для консольных программ всю эту событийщину скрыли, хитрым образом на уровне ОС засинхронизировав два потока: один отвечает за поддержание консольного окна, второй — собственно программа. А Pascal.ABC пришлось наладить простейшую эмуляцию, сделав «видеопамять» в виде внутреннего буфера.

    Так что придётся подключать события — см. pascalabc.net/downloads/pabcnethelp/scr/PABCUnits/... — и смотреть, какие в этой абстракции найдутся дыры. А они, по Спольскому, будут обязательно: TCP — это протокол гарантированной доставки, но кто её гарантирует, когда физически выдернули провод…
    Ответ написан
    9 комментариев
  • Почему возникает ошибка LNK2001 Неразрешенный внешний символ символ?

    @Mercury13
    Программист на «си с крестами» и не только
    Как говорят, «или крест снимите, или трусы наденьте». И учите понятие «единица компиляции».
    По какой схеме устроен ваш проект? «Одна единица компиляции» или «много единиц компиляции»?

    Си недалеко ушёл от ассемблеров. А в ассемблерах программа компилировалась по частям и собиралась воедино линкером (компоновщиком, редактором связей) — в те времена кода было много, а данных мало. Многие из ошибок невозможно было определить, не запустив линкер. Си++ пользуется многими из архитектурных особенностей ассемблеров и Си — по крайней мере ни одно из модульных решений не стало рекомендацией (кроме костыля extern template class).

    Но как говорить «переменная/функция есть, такого-то типа и в другой единице компиляции»? Для этого есть прототипы функций и extern-определения переменных. Их обычно вносят в заголовочные файлы с таким требованием: ничего, что находится в заголовочном файле, не должно производить кода. А код производят…
    • Глобальные переменные (без typedef, extern).
    • Нешаблонные функции (кроме inline).
    • Полностью специализированные шаблонные функции (кроме inline).
    • Команда «специализировать шаблон» (template class).

    При этом…
    • Функции в теле struct/class автоматически inline и кода не производят.
    • Для неявной специализации шаблонов существуют обходы — код генерируется дважды, но ошибки не выдаёт.
    • «Свой» хедер обычно включают первым, чтобы убедиться, что в нём нет недостающих зависимостей.

    В системе «одна единица компиляции» всё просто: есть ровно один файл, подлежащий компиляции. Тогда в хедерных файлах вполне могут быть конструкции, производящие код.

    Системы «одна единица компиляции» и «много единиц компиляции» можно комбинировать, но надо знать:
    • Все хедеры, которые производят код, должны подключаться из одной-единственной единицы компиляции. Надо чётко осознавать, из какой, и не подключать из чужих.
    • У библиотеки всё равно должен быть хедер-фасад, не производящий кода и предназначенный для стыковки с другими единицами компиляции.
    Такая конструкция ускоряет полную перекомпиляцию и часто применяется для библиотек, но надо знать: огромные библиотеки вроде SqLite, в 5 мегабайт препроцессированного кода, мешают распараллеливанию компиляции (ибо пока откомпилируется SqLite, остальные процессоры вполне себе соберут остальную программу).

    // В схеме «одна единица компиляции»: ничего не делать.
    // В схеме «много единиц компиляции»: лишняя зависимость; унести в unit1.cpp
    #include <cstdlib>
    
    // В схеме «одна единица компиляции»: убрать extern.
    // В схеме «много единиц компиляции»: завести unit1.cpp, там сделать MyType x;
    extern MyType X;
    
    // В схеме «одна единица компиляции»: ничего не делать.
    // В схеме «много единиц компиляции»: перенести функцию в unit1.cpp, оставив в .h только прототип.
    void XReset() {}
    Ответ написан
    Комментировать
  • Как написать SMTP-клиент, чтобы не попасть в список спамеров?

    @Mercury13
    Программист на «си с крестами» и не только
    Да уж, злой там спамодетектор…
    Написать сообщение реальным почтовиком и повторить как можно больше полей из этого самого почтовика.
    Пожалуй, главное — User-Agent. Процентов 80 ботофильтров ссылаются именно на него.
    Ответ написан
    Комментировать
  • Тихий звон в БП при обращении к винчестеру — что скажете?

    @Mercury13 Автор вопроса
    Программист на «си с крестами» и не только
    Ремонтника так и не объявилось, а я сменил матплату и виновата именно она. Так не хочется отмечать себя…
    Ответ написан
    Комментировать
  • Какие данные приходят на устройство через COM-порт, если отправить "1"?

    @Mercury13
    Программист на «си с крестами» и не только
    Перед нами такая конструкция
    0 . 1000 . 1100 . 1 . 0 . 0101 . 0000 . 1
    Каждый байт начинается стартовым битом 0 и кончается стоповым битом 1. Передаётся, начиная с младшего бита.
    Итого два байта, 31+0A, или "1" + LineFeed.
    Ответ написан
    9 комментариев
  • Как найти координаты прямой d, направленного по биссектрисе угла между двумя прямыми, при условии, что длина бисс прямой с задается с клавиатуры?

    @Mercury13
    Программист на «си с крестами» и не только
    Как я понял, задача такова. Есть угол, заданный вершиной и двумя точками на сторонах. Найти, куда попадёт биссектриса длины 4.

    1. Из координат вершины угла и точек на его сторонах получить векторы-стороны.
    2. Привести векторы-стороны к единой длине (например, разделить на длину).
    3. Их среднее арифметическое — вектор-биссектриса. Если получился нулевой вектор — векторы-стороны смотрят на 180°, и непонятно, в какую сторону считать нашу биссектрису.
    4. Привести вектор-биссектрису к нужной длине (разделив на реальную длину и умножив на требуемую).
    5. Отсчитать этот вектор от вершины угла. Получится координата биссектрисы длины 4, отложенной от точки (3, 4).
    А математика совсем не высшая :)
    Ответ написан
    Комментировать
  • Как сделать двухстрочную шапку в таблице в С++ Builder?

    @Mercury13
    Программист на «си с крестами» и не только
    Нельзя, я использовал компонент KGrid.
    Ответ написан
    Комментировать
  • Лучше ли книги онлайн - курсов?

    @Mercury13
    Программист на «си с крестами» и не только
    Онлайн лучше.
    1. Объяснить сложный принцип действия, когда видео действительно подспорье. Например, рассказать в динамике о том, как работает сложный шифропротокол.
    2. Рассказать о простых стандартных задачах. Впрочем, и в этом я не уверен.
    3. Ткнуть носом в нужное место интерфейса.

    Печатный материал лучше.
    1. Когда нужно посидеть и осознать. Первые шаги в вашем первом языке программирования, когда даже синтаксис стена. Практически всё, что относится к алгоритмам.
    2. Работа с низкоуровневыми библиотеками наподобие OpenGL или SDL, которые производят кучу кода.
    3. Небольшой справочник.
    Ответ написан
    Комментировать
  • Почему данный код блокирует UI?

    @Mercury13
    Программист на «си с крестами» и не только
    Потому что OpenFileDialog модальный.
    Добавили ключевое слово async и ждёте другого поведения стандартного диалога Windows?
    Ответ написан
  • Как пропустить весь поток для того, чтобы можно было воспользоваться getchar()?

    @Mercury13
    Программист на «си с крестами» и не только
    fflush(stdin);

    Но такое поведение «новодел» и не заспецифицировано жёстко. В Windows работает, в Linux, говорят, тоже, а в BSD и его производных (Mac) — уже нет.

    Кто-то подсказывает такую штуку
    if ( ferror( stdin ) || feof( stdin ) )
        clearerr( stdin );
        else rewind( stdin );
    Ответ написан
    2 комментария