我正在尋找函數來可靠地將字符串轉換爲雙精度,然後返回到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