Std:: decimal:: decimal64 правильное использование, g++ 4.6.3

Я изучаю замену двойников в нашем коде на g++ std:: decimal:: decimal32/64/128 типов для целей сумм валют и цен, однако я зацикливаюсь на том, как наилучшим образом вводить и выводить данные. В частности, не существует каких-либо подпрограмм для преобразования в/из строки, а механизмы stringstream не компилируются для этих типов. Единственный способ, которым я это вижу, - использовать double в качестве промежуточного типа, однако, конечно, это, по крайней мере, частично поражает цель использования десятичных типов, если мы всегда вводим и выводим через двойники?

Я уверен, что я не понимаю что-то здесь, так что бы приветствовать некоторые отзывы о том, как лучше использовать эти типы.

Edit:

Я взломал пару процедур ввода/вывода, но я тоже не очень доволен. Ввод вряд ли является надежным (без поддержки научной нотации), а процедура вывода упрощена, не говоря уже о неэффективности из-за двойного преобразования.

#define MAX_DEC_LEN 17

std::decimal::decimal64 FromString(const char* str)
{
    if (strlen(str) > MAX_DEC_LEN)
        throw std::runtime_error("bad input");
    char buf[MAX_DEC_LEN+1];
    strncpy(buf, str, MAX_DEC_LEN+1);
    char* point(NULL); 
    if ((point = strchr(buf, '.')) != NULL)
        *(point++) = '\0';
    std::decimal::decimal64 ret(atoi(buf));
    if (point != NULL && *point != '\0')
    {
        int exponent(strlen(point));
        long long unsigned coeff(atoi(point));
        std::decimal::decimal64 d2(std::decimal::make_decimal64(coeff, -exponent));
        if (*buf == '-')
            ret -= d2;
        else
            ret += d2;
    }
    return ret;    
}

std::string ToString(std::decimal::decimal64 dec)
{
    double d(std::decimal::decimal_to_double(dec));
    std::ostringstream oss;
    oss << std::fixed << std::setprecision(6) << d;
    return oss.str();
}

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

Ответ 1

Decimal TR определяет перегрузки для ввода и вывода в разделах 3.2.10 и 3.2.11 соответственно. По внешнему виду они не реализованы gcc. Десятичная поддержка в gcc реализована в терминах libdecnum, которая предоставляет процедуры для преобразования из и в строки. Я бы создал простую реализацию операторов ввода-вывода, используя их для начала работы.

Изменить в 2012-10-17: глядя на форматирование десятичных значений в gcc-библиотеке (std::decimal::decimal64 и family), выяснилось, что gcc, к сожалению, не устанавливает ни заголовки библиотеки decNumber, ни библиотеку. Кроме того, другие источники decNumber не совсем совпадают с доставкой версии с gcc. В результате единственный способ найти десятичные числа, отформатированные, состоит в том, чтобы использовать явные объявления и использовать сборку библиотеки при компиляции gcc.

Простая часть является источником, хотя и для довольно простой реализации. Во-первых, декларация, которая попадает в подходящий заголовок, например. <decimal/decimal>:

std::ostream& operator<< (std::ostream&, std::decimal::decimal32 const&);
std::ostream& operator<< (std::ostream&, std::decimal::decimal64 const&);
std::ostream& operator<< (std::ostream&, std::decimal::decimal128 const&);

Довольно простая реализация чего-то, делающего некоторое форматирование, хотя без каких-либо параметров может выглядеть так:

extern "C" char* decimal32ToString(std::decimal::decimal32 const*, char*);
extern "C" char* decimal64ToString(std::decimal::decimal64 const*, char*);
extern "C" char* decimal128ToString(std::decimal::decimal128 const*, char*);

std::ostream& operator<< (std::ostream& out,
                          std::decimal::decimal32 const& value)
{
    char buffer[128];
    decimal32ToString(&value, buffer);
    return out << buffer;
}

std::ostream& operator<< (std::ostream& out,
                          std::decimal::decimal64 const& value)
{
    char buffer[128];
    decimal64ToString(&value, buffer);
    return out << buffer;
}

std::ostream& operator<< (std::ostream& out,
                          std::decimal::decimal128 const& value)
{
    char buffer[128];
    decimal128ToString(&value, buffer);
    return out << buffer;
}

С этим на месте все еще остается проблема, из-за которой мне не удалось создать что-либо с использованием десятичных знаков, если не используется некоторый уровень оптимизации, т.е. -O1 (или выше). При отсутствии оптимизации используются символы без ссылок, но это совершенно не связано с печатью значений. Чтобы получить определения функций, используемых в реализации, мне нужно было связать с библиотекой libdecnumber.a, которая создается во время сборки gcc:

g++ -o prog decimal-io.cpp main.cpp <gcc-build-root>/libdecnumber/libdecnumber.a

Кроме того, у меня есть моя собственная реализация Decimal TR с некоторое расширение, и основывая его на библиотеке decnumber и правильно внедряя I/O. Моя реализация, надеюсь, станет общедоступной в какой-то момент, но не скоро.