我正在寻找函数来可靠地将字符串转换为双精度,然后返回到C++中的字符串,以便输出字符串与输入字符串完全相同。但即使经过数小时的搜索和尝试,我也找不到可靠的功能。可靠转换字符串双打和返回
要检查功能是可靠的我做了如下试验:
#include <iostream>
#include <string>
using namespace std;
string double2string(double value){
//...
}
double string2double(string value){
//...
}
int main(){
string strings[] = {
"111111111111110000",
"11111111111111000",
"1111111111111100",
"111111111111110",
"11111111111111",
"1111111111111.1",
"111111111111.11",
"11111111111.111",
"1111111111.1111",
"111111111.11111",
"11111111.111111",
"1111111.1111111",
"111111.11111111",
"11111.111111111",
"1111.1111111111",
"111.11111111111",
"11.111111111111",
"1.1111111111111",
"0.11111111111111",
"0.011111111111111",
"0.0011111111111111",
"0.00011111111111111"
};
double doubles[] = {
111111111111110000,
11111111111111000,
1111111111111100,
111111111111110,
11111111111111,
1111111111111.1,
111111111111.11,
11111111111.111,
1111111111.1111,
111111111.11111,
11111111.111111,
1111111.1111111,
111111.11111111,
11111.111111111,
1111.1111111111,
111.11111111111,
11.111111111111,
1.1111111111111,
0.11111111111111,
0.011111111111111,
0.0011111111111111,
0.00011111111111111
};
for(int i = 0; i < 22; i++){
cout
<< (string2double(strings[i])==doubles[i])
<< " "
<< (double2string(doubles[i])==strings[i])
<< endl;
}
return 0;
}
“?为什么这个测试”,你可能会问。让我解释一下: C++ double有52位来保存一个整数。这个数字最高可以是2^52-1,或者4503599627370495。这个数字是16位数字。但由于并非所有16位数字的数字都适合那些没有溢出的位,我的要求是只可靠地转换所有15位数字的数字。前导或尾随零不计数,因为它们可用11个指数位表示。
所以,基本上,我确保所有这些数字在理论上都适合双倍,没有任何溢出,以便我可以将它们1:1转换回字符串。
现在:您是否知道任何函数可以从double转换为string并返回,只需打印出“1”即可完成测试?
您的测试基于有缺陷的假设,例如,“X.1”可以首先表示为double(它不能)。如果*用double开始*,将其转换为字符串,打印字符串,然后转换为double,则会发现它按照您的预期进行往返。但并不是每个数字实际上都可以表现为一个双。基本上,无论你有多精确,都有一些数字不能用基2指数表示法表示,这就是浮点数的编码方式。 – aruisdante 2014-10-29 13:56:57
他们不“理论上适合双倍”。没有一个小数值可以用二进制浮点格式精确表示。如果您需要准确表示非整数小数,则需要使用不同的表示法。 – 2014-10-29 13:57:12
@tgmath带来了非常好的一点。除非你指定为双字面值,否则通过'=='比较任意两个双精度的几率是天文数字低的,这要归功于前面提到的双精度内在的数字不稳定性。这就是为什么,例如'for(double i = 0.0; i!= 1.0; i + = 0.1)'将永远不会终止。 – aruisdante 2014-10-29 14:01:39