2009-06-05 3 views
1

У меня есть три набора чисел, измерение (которое находится в диапазоне 0-1 включительно) две ошибки (положительные и отрицательные). Эти числа должны отображаться последовательно с количеством значимых цифры, округленные вверх, что соответствует первой ненулевой записи в любом из чисел.Правильное форматирование чисел с ошибками (C++)

Это требование пропускается при измерении, если оно одно (т.е. необходимо учитывать только цифры в ошибках). :

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

Есть ли ограничение, что ваша реализация не используют библиотечные вызовы? –

+0

Не совсем понятно. Ehy на первой строке числозначимых цифр равно 2, а на втором - 1? Другими словами, почему в первой строке +0.0форматируется как +0.00, но во второй строке +0.0 форматируется как +0.0? –

+0

Я не совсем понимаю - вы говорите, что хотите отобразить до первой ненулевой цифры, но ваш пример показывает +0.00, а не +0.001. –

ответ

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

Мало того, что это решение не отвечает на весь вопрос, но у него есть ошибка - что происходит с ведущими нулями на терминах% 100? –

+0

Хорошо поймать ошибку. –

+0

ss << ФорматNum (+0.0000134); дает неверные результаты – LeBleu

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); 

перед тем, как вы вывести номера, следует делать то, что вы ищете.

Edit: в качестве примера

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(); 
}