我正在研究用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);
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();
}
我真的在为这两个方面做了更好的事情,加上一轮(特别精确)来解决问题(原谅双关语)
答案 0 :(得分:6)
Decimal TR分别定义了3.2.10和3.2.11节中输入和输出的重载。从它的外观来看,它们不是由gcc实现的。 gcc中的十进制支持是根据libdecnum实现的,它提供了从字符串转换为字符串的例程。我将使用它们来创建一个简单的I / O操作符实现。
在2012-10-17编辑:看看格式化gcc库(std::decimal::decimal64
和系列)中的十进制值,发现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
(或更高)。除非使用优化,否则存在未引用的符号,但这与打印值完全无关。为了获得实现中使用的函数的定义,我需要链接到在构建gcc时创建的libdecnumber.a
库:
g++ -o prog decimal-io.cpp main.cpp <gcc-build-root>/libdecnumber/libdecnumber.a
除此之外,我有自己Decimal TR和some extension的实现,并将其基于decnumber库并正确实现I / O.我的实施有望在某个时候公开发布,但不会很快公开。