如@bsruth提到的,默認格式是相當於%g
爲fprintf
,和與此行爲指定:
令P等於精度如果非零,6如果不是指定精度,或者如果精度爲0,則爲1。
然後,如果用式E中的轉換將具有X的指數:
如果P> X≥-4,轉換是具有式F或F和精度p - 1 - X.
否則,轉換風格e或E和精度p - 1
因此,如果需要,我們計算base10指數,因爲它是在科學記數法並用它來調整精度下降:
#include <cmath>
#include <limits>
#include <string>
#include <sstream>
double frexp10_scientific(double arg, int* exp)
{
*exp = (arg == 0) ? 0 : static_cast<int>(std::log10(std::fabs(arg)));
double fraction = arg * pow(10 , -(*exp));
// adjust to scientific format decomposition
if (std::fabs(fraction) < 1.0) {
*exp -= 1;
fraction *= 10;
}
return fraction;
}
template <typename T>
int precision_needed(T val)
{
// initial guess on precision
int precision;
if (val >= 0.0) {
if (val >= 1e15 && val < 1e16)
precision = 16; // all integer digits used
else
precision = 15; // '.' present
} else {
if (val > -1e15 && val <= -1e14)
precision = 15; // '-' present, all integer digits used
else
precision = 14; // '-' and '.' present
}
int exp;
frexp10_scientific(val, &exp);
// adjust for scientific notation if needed
if (exp < -99) {
precision -= 5; // "e-123"
} else if (exp < -4) {
precision -= 4; // "e-01"
} else if (exp >= precision) {
if (exp > 99) {
precision -= 5; // "e+123"
} else {
precision -= 4; // "e+12"
}
}
return std::min(precision, std::numeric_limits<T>::max_digits10);
}
template <typename T>
std::string format(T val) {
std::ostringstream oss;
oss.precision(precision_needed(val));
oss << val;
return oss.str();
}
一些test cases,顯示輸入,精密,長和輸出:
1.123e-4: [p=15,l=9] 0.0001123
1.123e-5: [p=11,l=9] 1.123e-05
1.123e-99: [p=11,l=9] 1.123e-99
1.123e-100: [p=10,l=10] 1.123e-100
7.105427357601002e-14: [p=11,l=16] 7.1054273576e-14
7.105427357621342e-14: [p=11,l=16] 7.1054273576e-14
-7.105427357601002e-14: [p=10,l=16] -7.105427358e-14
-7.105427357621342e-14: [p=10,l=16] -7.105427358e-14
7.105427357621342e14: [p=15,l=15] 710542735762134
7.105427357621342e15: [p=16,l=16] 7105427357621342
7.105427357621342e16: [p=11,l=16] 7.1054273576e+16
-7.105427357621342e14: [p=15,l=16] -710542735762134
-7.105427357621342e15: [p=10,l=16] -7.105427358e+15
7.105427357621342e15: [p=16,l=16] 7105427357621342
7.105427357621342e16: [p=11,l=16] 7.1054273576e+16
-7.105427357621342e15: [p=10,l=16] -7.105427358e+15
1.123e14: [p=15,l=15] 112300000000000
1.123e15: [p=16,l=16] 1123000000000000
1e15: [p=16,l=16] 1000000000000000
1e16: [p=11,l=5] 1e+16
-1e15: [p=10,l=6] -1e+15
-1e14: [p=15,l=16] -100000000000000
1.23456789e-14: [p=11,l=16] 1.2345678901e-14
你是不是想左(右)修剪長雙文字,圓它,或根據模板類型的數字限制? – Ron
@Ron的問題基本上是:「鑑於我的存儲(以字節爲單位)的大小,我怎麼打印'double'爲最大精度可能適合在長度」 – Justin
元的問題:有多少精做你的實際需要爲您的應用程序?多少(相對/絕對)錯誤是可以接受的?你確定計算錯誤並不占主導地位嗎? –