我有这三个数字:
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;
}
这适用于n1
和n3
个案例,但当我使用n2
时,它会返回1
而不是10
。
我正在考虑如何解决这个问题,唯一的办法是在转换为字符串然后再次设置精度之前计算精度。
这是一个可行的策略吗? 如何计算该点之后有多少位数?
答案 0 :(得分:2)
如果您的数字最初出现在数据类型double
中,那么我认为没有机会将小数部分分开,如用于初始化的文字中所写。由于我将尝试在以下段落中解释,因此这些信息就会丢失:
请注意,文字1.10
和1.1
都代表double
类型的数字文字。编译器将两个文字转换为浮点表示/二进制表示,1.10
和1.1
将实现完全相同的二进制表示。因此,您没有机会查明是否已使用文字1.1
或1.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!
因此,您无法再区分n1
和n2
。
很多单词和简短的结论:
如果您想区分1.1
与1.10
,或者您通常想要找出源代码中所写的数字文字的小数部分,那么您必须存储它们最初作为字符串,而不是双打。
答案 1 :(得分:0)
我猜你不熟悉实际上是什么'浮点数'。
double是https://en.wikipedia.org/wiki/IEEE_floating_point中描述的浮点数。基本上1.10
与1.1
相同,与1.1000000
相同,依此类推。
现在,有一种称为“固定点数”的解决方案,通常称为“小数”和“数字”。如果您熟悉数据库引擎,则知道1.10是数字(3,2)而1.1是数字(2,1)。注意类型如何更改并定义精度(位数)和比例(逗号后的位数)。但是,C ++本身不支持小数。
答案 2 :(得分:-2)
这只是简单的数学。 解析器只是将你的x.10转换为x.1:)