التنسيق الصحيح للأرقام مع الأخطاء (C ++)
-
12-09-2019 - |
سؤال
لدي ثلاث مجموعات من الأرقام، وهو قياس (وهو موجود في النطاق 0-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 ++. الكل وأي أفكار موضع ترحيب!
المحلول
بلدي 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();
}
نصائح أخرى
استخدام
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
مزيد من التحرير: من الواضح أنك يجب أن تضطر إلى ضبط الدقة لتتناسب مع شخصياتك المهمة.
ربما شيء مثل:
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);
لست متأكدا تماما من الطريقة التي ستساعدك فيها 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
}
قد لا يكون هذا الحل الأكثر أناقة، لكنني أعتقد أنه يعمل (لم أحاول ذلك)
إليك اختلاف على الإصدار المقدم من شين باول.
std::string FormatNum(double num, int decimals)
{
stringstream ss;
if (num >= 0.0)
ss << '+';
ss << setiosflags(ios::fixed) << setprecision(decimals) << num;
return ss.str();
}