std :: decimal :: decimal64正确的用法,g ++ 4.6.3 [英] std::decimal::decimal64 correct usage, g++ 4.6.3

查看:587
本文介绍了std :: decimal :: decimal64正确的用法,g ++ 4.6.3的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究用g ++的std :: decimal :: decimal32 / 64/128类型代替货币数量和价格的双重代码,但是我被困在如何最佳输入并输出数据。具体而言,似乎没有任何用于转换字符串的例程,并且字符串流机制不会针对这些类型进行编译。我看到这样做的唯一方法是使用double作为中间类型,但是如果我们总是通过双精度输入和输出,这肯定会至少部分地破坏使用小数类型的目的?



我确定我在这里没有理解某些东西,因此欢迎您提供一些关于如何最好地使用这些类型的反馈。



编辑:

我已经把一些输入/输出例程一起砍了,但是我对这两个例程并不满意。输入不稳健(没有科学记数法支持),输出例程简单化,更不用说由于双重转换造成的低效。

  #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); ((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;

$ b $ 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();
}

对于这两种情况, (赦免双关语)

解决方案

Decimal TR , 分别。从它的外观来看,它们不是由gcc实现的。 gcc中的十进制支持是通过libdecnum实现的,它提供了从字符串转换为字符串的例程。我将创建一个使用它们的I / O操作符的简单实现。



编辑于2012-10-17:查看格式化gcc库中的十进制值( std :: decimal :: decimal64 和family)显示gcc遗憾地不安装decNumber库头文件或库。此外, decNumber 的其他来源与使用gcc的版本并不完全一致。因此,到目前为止我发现获得格式化十进制数的唯一方法是使用显式声明并在编译gcc期间使用库构建。



简单的部分是来源,虽然相当简单的实现。首先,将进入合适标题的声明,例如< decimal / decimal>

  std :: ostream&运营商LT;< (std :: ostream&,std :: decimal :: decimal32 const&); 
std :: ostream&运营商LT;< (std :: ostream&,std :: decimal :: decimal64 const&);
std :: ostream&运营商LT;< (std :: ostream&,std :: decimal :: decimal128 const&);

一个相当简单的实现某些格式化的东西,尽管没有任何选项可能看起来像这样: p>

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

std :: ostream&运营商LT;< (std :: ostream& out,
std :: decimal :: decimal32 const& value)
{
char buffer [128];
decimal32ToString(& value,buffer);
退货<<缓冲;
}

std :: ostream&运营商LT;< (std :: ostream& out,
std :: decimal :: decimal64 const& value)
{
char buffer [128];
decimal64ToString(& value,buffer);
退货<<缓冲;
}

std :: ostream&运营商LT;< (std :: ostream& out,
std :: decimal :: decimal128 const& value)
{
char buffer [128];
decimal128ToString(& value,buffer);
退货<<缓冲;
}

有了这个,仍然存在一个我没有管理的问题除非使用一些优化级别,即 -O1 (或更高),否则使用小数构建任何内容。除非使用优化,否则存在未引用的符号,但这与打印值完全无关。为了获得在实现中使用的函数的定义,我需要链接到在构建gcc时创建的 libdecnumber.a 库:

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

除此之外,我还有自己的 Decimal TR with 一些扩展,并将其基于decnumber库并正确实施I / O。希望我的实施将在某些时候公开,但不会很快。


I'm investigating the replacing of doubles in our code with g++'s std::decimal::decimal32/64/128 types for purpose of currency amounts and prices, however I'm getting stuck on the point of how to best input and output the data. Specifically, there do not appear to be any routines for converting to/from a string, and the stringstream mechanisms do not compile for these types. The only way I see doing this is to use double as an intermediate type, however surely this at least partially defeats the purpose of using the decimal types if we're always inputting and outputting via doubles?

I'm sure I'm not understanding something here so would welcome some feedback on how best to use these types.

Edit:

I have hacked together a couple of input/output routines, however I'm not really satisfied with either. The input is hardly robust (no scientific notation support) and the output routine is simplistic, not to mention inefficient due to the double conversion.

#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();
}

I'm really after something better for both of these, plus a round (to a particular precision) to round things off (pardon the pun)

解决方案

The Decimal TR defines overloads for input and output in sections 3.2.10 and 3.2.11, respectively. From the looks of it they are not implemented by gcc. The decimal support in gcc is implemented in terms of libdecnum which provides routines to convert from and to strings. I would create a simple implementation of the I/O operators using them to get started.

Edit on 2012-10-17: Looking at formatting the decimal values in gcc's library (std::decimal::decimal64 and family) revealed that gcc unfortunately doesn't install either the decNumber library headers or the library. Furthermore, other sources of decNumber don't quite align with the version shipping with gcc. As a result, the only way I found so far to get decimal numbers formatted is to use explicit declarations and using the library build during compiling gcc.

The simple part is the source, although for a rather simple implementation. First, the declaration which would go into a suitable header, e.g. <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&);

A fairly simple implementation of something doing some formatting, although without any options could look like this:

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;
}

With this in place, there is still an issue that I didn't manage to build anything using decimals unless some level of optimization, i.e., -O1 (or higher), is used. There are unreferenced symbols unless optimization is used but this is entirely unrelated to printing the values. To get definitions of the functions used in the implementation, I needed to link to the libdecnumber.a library which is created while gcc is being build:

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

Aside from this I have my own implementation of the Decimal TR with some extension and basing it on the decnumber library and implement I/O properly. My implementation hopefully will become publicly available at some point but not any time soon.

这篇关于std :: decimal :: decimal64正确的用法,g ++ 4.6.3的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆