2016-03-01 75 views
0

我想一個double值轉換成std::string。目前我正在寫雙待的std :: string具有動態precisicion(無尾隨零)

return std::to_string(double_value); 

但這只是返回7位,因爲內部to_string()只是使用std::vsnprintf%f格式說明(見here)。

我現在可以使用%.15f作爲格式說明符手動調用std::vsnprintf,但這會導致尾隨零。

我(在我眼裏很明顯的),現在的目標是有一個這樣的方法:

string o1 = to_string(3.14) 
string o2 = to_string(3.1415926536) 
assert(o1 == "3.14") 
assert(o2 == "3.1415926536") 

Here是從%.20輸出修剪尾隨零一個很好的闡述,但是這個答案是8歲左右。

也許事情已經改變?我可以用雙精度將double轉換成今天的C++中沒有拖尾零嗎?

解決方案:

基於2man的答案,你可以寫一個通用的函數是這樣的:

template<typename T> 
inline std::string tostr(T value) { 
    std::ostringstream s; 
    s.precision(std::numeric_limits<T>::digits10); 
    s << value; 
    return s.str(); 
} 

這將表現得像所需的數字類型。請注意,我把digits10而不是max_digits10贊成一個不錯的十進制表示,而不是更多的數字和尾隨..0000001

而且恕我直言,這是值得補充的是[v][s][n]printf()與格式字符串「%0.15 」在一起(而不是' f')也將修剪尾隨零(不會用更多的數字工作,因爲它們不能用64位表示,這會導致尾隨'1',例如3.12→3.1200000000000001)

Still奇怪

也許有人可以告訴我爲什麼std::to_string(double)是用C++ -11硬編碼引入到vsnprintf(..., "%f", ...)而不是像vsnprintf("%.15g")那樣會導致更精確的表示而不影響C代碼?

+0

的一個好處是,它是非常* *向後兼容。在鏈接的答案C代碼是八歲也沒關係,它仍然可以工作,並沒有相關的已與C11標準的改變。它不應該很難翻譯成C++。沒有這樣的事情,這是不可能的,除非事實上知道有效數字的數量。 –

+1

如果是八歲個小時舊不要緊:好的代碼是好的代碼。 (另外,它是C++ ...它沒有太大變化)。 – Ellis

+1

你打算如何處理浮點四捨五入?我試圖簡單地向字符串添加字符,但是當存儲在內存中時,「3.14」可能不完全是'3.14'。在不限制數字的情況下,當你想要2.12時可以得到'2.12000000005'。 – Matt

回答

2

您可以使用流操縱字符串流(sstring),見下面的例子:

std::stringstream ss1; 
    std::stringstream ss2; 
    ss1.precision(15);  
    ss1 << 3.14; 
    std::cout << ss1.str()<<' '<<("3.14" == ss1.str())<<std::endl; 
    ss2.precision(15); 
    ss2 << 3.1415926536; 
    std::cout << ss2.str()<<' '<<("3.1415926536" == ss2.str())<<std::endl; 

或者您可以使用升壓格式。這是a link!關於C

std::cout<<format("%.2f") % 3.14 <<std::endl; 
    std::cout<<format("%.10f") % 3.1415926536 <<std::endl; 
+0

在這個例子中,您仍然必須手動指定精度。使用'vsnprintf()',如果不爲'%f'添加精度,它將被正確修剪,但它只限於7位數。 – frans

+0

您可以將精度設置爲15.當您將流投射到字符串時,字符串將在末尾不包含「0」。 – 2man

+0

你是對的 - 你不能使用可以用'double'表示的最大小數位數(也就是17)。 (看我的編輯) – frans