Стек C++ для нескольких типов данных (векторный калькулятор RPN)

Я разработал быструю и основную векторную арифметическую библиотеку на C++. Я вызываю программу из командной строки, когда мне нужно быстрое перекрестное произведение или угол между векторами. Я не использую Matlab или Octave или связанные с ними, потому что время запуска больше, чем время вычислений. Опять же, это для очень простых операций.

Я расширяю эту программу и заставлю ее работать как калькулятор RPN для операций типа:

1 2 3
4 5 6
x
out: -3 6 -3

(дайте один вектор, другой вектор и оператор "крест"; выложите перекрестное произведение)

Стек должен принимать трехмерные векторы или скаляры для таких операций, как:

1 2 3
2
*
out: 2 4 6

Лексер и парсер для этого мини-калькулятора тривиальны, но я не могу придумать хорошего способа создания внутреннего стека. Как бы вы создали стек для размещения векторов или двойников (я свернул свой собственный очень простой векторный класс - менее ста строк, и он делает все, что мне нужно).

Как я могу создать простой стек, который принимает элементы класса Vector или типа double?

Спасибо.

3 ответа

Решение

Простейшим способом было бы просто создать Operand структура, которая содержит double для скаляра и Vector объект для вектора:

struct Operand
{
    double scalar_;
    Vector vector_;
    bool isVector_;
};

(вы можете установить isVector_ true, если это векторный операнд, и false, если это скалярный операнд)

Для фактического стека вы можете просто использовать std::stack<Operand>,

Другие варианты включают наследование (создание скалярных и векторных типов, полученных из базового типа операнда) или что-то вроде boost::variant, но для чего-то простого, как это, структура композиции, как Operand показанный выше, вероятно, самый простой способ сделать это.

Одним из решений является использование союзов. Союзы, вы можете использовать одну и ту же область памяти для разных структур. Например, у вас может быть одна двойная и одна структура в объединении. Они разделяют одну и ту же память, и вы можете использовать только один из них. Вы можете использовать некоторое перечисление, чтобы сказать, какой из них использовать.

Союзы немного хакерские, потому что они делают использование объектов более хитрым. Компилятор не знает, как создавать, разрушать или копировать их, потому что многие объекты могут совместно использовать одну и ту же память. Вот небольшой пример того, как я мог бы сделать это, если бы я хотел сэкономить память (хорошо, enum занимает четыре байта и, следовательно, неэффективно использует память, но давайте забудем об этом;)

#include <cstdlib>
#include <iostream>

struct Vector
{
    double x, y, z;
};

struct Element
{
    enum Type { SCALAR, VECTOR };
    Type type;
    union {
        double scalar;
        Vector v;
    } data;
};

int main(void)
{
    Element vector_element;
    vector_element.type = Element::VECTOR;
    vector_element.data.v.x = 1;
    vector_element.data.v.y = 2;
    vector_element.data.v.z = 3;

    Element scalar_element;
    scalar_element.type = Element::SCALAR;
    scalar_element.data.scalar = 3.142;

    std::cout << "The size of type Element without enum would be: " << (sizeof(Element) - sizeof(Element::Type)) << " bytes." << std::endl;

    return EXIT_SUCCESS;
}

Кстати, по какой-то странной причине это приводит к 28 байтам. Я ожидал 3 * 8 = 24 байта.

Вы смотрели на повышение:: любой?

Другие вопросы по тегам