2009-06-05 34 views
1

我有三组数字,一个测量(在0-1范围内)两个错误(正数和负数,这些数字应该一致地显示为显着数数字向上取整,相当于第一个非零数字中的任何一个数字正确格式化有错误的数字(C++)

如果测量结果为1(即只有错误中的数字需要考虑),该要求会被跳过。 :

0.95637 (+0.00123, -0.02935) --> 0.96 +0.00 -0.03 
1.00000 (+0.0, -0.0979) --> 1.0 +0.0 -0.1 (note had to truncate due to -ve error rounding up at first significant digit) 

现在,获取第一个非零数字很容易通过采取log10(num),但我有一个愚蠢的时刻试图以干净的方式进行剥离和修圆工作。

所有数据类型都是双打的,选择的语言是C++。欢迎任何想法!

+0

是否有您的实现不使用库调用的约束? – 2009-06-05 22:13:47

+0

这并不完全清楚。 Ehy在第一行有效数字的位数是2,第二位是1?换句话说,为什么在第一行+0.00123被格式化为+0.00,但在第二行+0.0被格式化为+0.0? – 2009-06-05 22:28:48

回答

2

我的C++是锈迹斑斑,但不会下做到这一点:

std::string FormatNum(double measurement, double poserror, double negerror) 
{ 
    int precision = 1; // Precision to use if all numbers are zero 

    if (poserror > 0) 
    precision = ceil(-1 * log10(poserror)); 
    if (negerror < 0) 
    precision = min(precision, ceil(-1 * log10(abs(negerror)))); 

    // If you meant the first non-zero in any of the 3 numbers, uncomment this: 
    //if(measurement < 1) 
    // precision = min(precision, ceil(-1 * log10(measurement))); 

    stringstream ss; 
    ss.setf(ios::fixed, ios::floatfield); 
    ss.precision(precision); 
    ss << measurement << " +" << poserror << " " << negerror ; 
    return ss.str(); 
} 
1

也许是这样的:

std::string FormatNum(double num) 
{ 
    int numToDisplay ((int)((num + 0.005) * 100.0)); 
    stringstream ss; 
    int digitsToDisplay(abs(numToDisplay) % 100); 
    ss << ((num > 0) ? '+' : '-') << (abs(numToDisplay)/100) << '.' << (digitsToDisplay/10) << (digitsToDisplay % 10); 
    return ss.str(); 
} 

    stringstream ss; 
    ss << FormatNum(0.95637) << ' ' << FormatNum(+0.00123) << ' ' << FormatNum(-0.02935); 
0

我不太清楚你如何是LOG10将有助于你得到的第一个非零数字,但假设它(因此你知道什么是小数位你被四舍五入到),下面的函数将正确轮:

double round(double num, int decimalPlaces) 
{ 
    //given your example of .95637 being rounded to two decimal places 
    double decimalMultiplier = pow(10, decimalPlaces); // = 100 
    double roundedShiftedNum = num * decimalMultiplier + 0.5; // = 96.137 
    double insignificantDigits = (roundedShiftedNum - (int)roundedShiftedNum; // = 0.137 
    return (roundedShiftedNum - insignificantDigits)/decimalMultiplier; // = (96.137 - 0.137)/100 = 0.96 
} 

这可能不是最完美的解决方案,但我相信它的工作原理(还没有尝试过,虽然)

2

使用

cout.setf(ios::fixed, ios::floatfield); 
cout.precision(2); 

在输出数字之前应该做你正在寻找的东西。

编辑:作为一个例子

double a = 0.95637; 
double b = 0.00123; 
double c = -0.02935; 

cout.setf(ios::fixed, ios::floatfield); 
cout.precision(2); 
cout << a << endl; 
cout << b << endl; 
cout << c << endl; 

将输出:

0.96 
0.00 
-0.03 

进一步编辑:你会明显地有调整精度,以符合您显著数字。

0

这是由Shane Powell提供的版本中的变更。

std::string FormatNum(double num, int decimals) 
{ 
    stringstream ss; 
    if (num >= 0.0) 
     ss << '+'; 
    ss << setiosflags(ios::fixed) << setprecision(decimals) << num; 
    return ss.str(); 
}