如何在c ++中解析和拆分double

时间:2017-04-14 08:17:10

标签: c++ string type-conversion double precision

我有这三个数字:

double n1 = 1.1
double n2 = 1.10
double n3 = 1.101

我期望将它们转换为字符串以分隔小数部分以在其他地方使用它们。因此,我希望有以下内容:

string s1 = 1
string s2 = 10
string s3 = 101

我读到使用std::to_string这是不可能的,因为它总是返回所有小数,例如s3类似于101000

然后我尝试了以下内容:

double n3 = 1.101;
std::ostringstream strs;
strs << n3;
std::string str = strs.str();

boost::char_separator<char> sep(".");
boost::tokenizer<boost::char_separator<char>> tokens(str,sep);

for (const auto& t : tokens) {
    EV << "separated parts " << t << endl;
}

这适用于n1n3个案例,但当我使用n2时,它会返回1而不是10

我正在考虑如何解决这个问题,唯一的办法是在转换为字符串然后再次设置精度之前计算精度。

这是一个可行的策略吗? 如何计算该点之后有多少位数?

3 个答案:

答案 0 :(得分:2)

如果您的数字最初出现在数据类型double中,那么我认为没有机会将小数部分分开,如用于初始化的文字中所写。由于我将尝试在以下段落中解释,因此这些信息就会丢失:

请注意,文字1.101.1都代表double类型的数字文字。编译器将两个文字转换为浮点表示/二进制表示,1.101.1将实现完全相同的二进制表示。因此,您没有机会查明是否已使用文字1.11.10初始化双值。

当我们认为十进制数1.1没有精确的二进制表示但导致重复分数时,事情变得更糟:

0.1₁₀ = 0.0001100110011001100110011001100110011001100110011…₂

因此,当您打印文字1.1(或1.10,它是相同的)时,它取决于您想要舍入的精度:

std::cout << "1.1 is..." << std::setprecision(6) << 1.1 << std::endl;
std::cout << "1.1 is..." << std::setprecision(17) << 1.1  << std::endl;
// 1.1 is...1.1
// 1.1 is...1.1000000000000001

这意味着 - 一旦存储为double值,您将获得不同的结果,具体取决于您用于打印值的精度;这也适用于将小数部分转换为字符串,这实际上与具有特定精度的打印相同。

更糟糕的是,由于无法以二进制形式精确表示每个十进制值,因此两个不同的十进制值可以以二进制形式产生相同的值:

double n1 = 1.1;
double n2 = 1.100000000000000088817841970012523233890533447265625;

if (n1 == n2)
    std::cout << "equal!" << std::endl;
// Output: equal!

因此,您无法再区分n1n2

很多单词和简短的结论:

如果您想区分1.11.10,或者您通常想要找出源代码中所写的数字文字的小数部分,那么您必须存储它们最初作为字符串,而不是双打。

答案 1 :(得分:0)

我猜你不熟悉实际上是什么'浮点数'。

double是https://en.wikipedia.org/wiki/IEEE_floating_point中描述的浮点数。基本上1.101.1相同,与1.1000000相同,依此类推。

现在,有一种称为“固定点数”的解决方案,通常称为“小数”和“数字”。如果您熟悉数据库引擎,则知道1.10是数字(3,2)而1.1是数字(2,1)。注意类型如何更改并定义精度(位数)和比例(逗号后的位数)。但是,C ++本身不支持小数。

答案 2 :(得分:-2)

这只是简单的数学。 解析器只是将你的x.10转换为x.1:)