Явное округление чисел до более чем 7 знаков после запятой в C++

Вот мой код:

double round( char* strNumber, int decPlace);

int main()
{
    int decimal;
         char initialNumber[256];

    cout << "Enter decimal and number " << endl;

    cin >> decimal;
    cin >> initialNumber;

    cout << setprecision (15) << round ( initialNumber,decimal ) << endl;   

return 0;
}

double round( char* strNumber, int decPlace)//
{
    double number = atof(strNumber);
    int temp = ( int ) ( pow(10.0,decPlace) * number + 0.5 );
    double result = ( double ) temp / pow(10.0,decPlace);
    return result;
}

Он работает до 6 знаков после запятой. В противном случае это дает какой-то странный результат. Ниже приведены числа, которые я использовал для тестирования и вывода:

Тест 1-раунд до 7 знаков после запятой

105.265

52.5689745694

25.6835

452.689785

12.456789877458

Выход

105.265

52.5689746

25.6835

-214.7483648

12.4567899

Тест 1-раунд до 8 знаков после запятой

Те же цифры, что и раньше

Выход

-21.47483648

-21.47483648

-21.47483648

-21.47483648

12.45678988

person Mike55    schedule 08.11.2009    source источник


Ответы (4)


Как уже говорили другие, приведение к int не будет работать с большими числами. Вместо этого вы можете использовать floor и сохранить число для округления в double:

#include <cstdlib>
#include <cmath>

double round( char* strNumber, int decPlace)
{
    double number = std::atof(strNumber);
    double expo = std::pow(10.0,decPlace);
    return std::floor( expo * number + 0.5) / expo;
}
person CB Bailey    schedule 08.11.2009
comment
@Pat: тогда ты должен принять ответ. - person jon-hanson; 08.11.2009

int может содержать меньший диапазон, чем double; на многих платформах его максимальное значение составляет около 2 миллиардов, что меньше pow(10.0,8) * number для большинства ваших входных чисел.

Вы можете сохранить свой номер как double и использовать floor для округления до целого числа:

double temp = floor( pow(10.0,decPlace) * number + 0.5 );
double result = temp / pow(10.0,decPlace);
person Mike Seymour    schedule 08.11.2009

Мне кажется, что переполнение. pow(10.0,decPlace) * number — довольно большое число — слишком большое, чтобы поместиться в 32-битное целое число (что, вероятно, и есть int на вашей платформе).

person Adam Wright    schedule 08.11.2009

int temp = ( int ) ( pow(10.0,decPlace) * number + 0.5 );

temp, вероятно, 32 бита. Он может вместить около +- 2 миллиардов. Переполнение.

person Richard Pennington    schedule 08.11.2009