2016-10-12 3 views
0

Я уже прочитал большинство вопросов, связанных с «округлением до n цифр». Я считаю, что этот вопрос является отдельным, потому что он больше связан с округлением всплывающих окон произвольной длины.Круглые произвольные поплавки до n цифр

0.56714329040978387299996866221035554975381578718651250813513107922304579308668456669321944696175229455773495728285284421635951688 

Число, приведенное выше, является примером типов чисел, с которыми я работаю.

Я понимаю, как округлить число в C++, это довольно просто. Тем не менее, я не понимаю, как я могу округлять произвольно-длинные числа до n цифр.

Например, у меня может быть число, состоящее из 192 цифр, которое мне нужно округлить до 84 цифр, или число, равное 1831 цифре, которое мне нужно округлить до 293 цифр. Как это можно сделать, используя одну функцию (или аналогичную)?

псевдокод для ясности, но я на самом деле с помощью увеличения многократной точности cpp_dec_float для произвольной точности поплавки вместо стандартных поплавков:

float round(float num, int digits){ 
    //returns num rounded to n digits 
} 

Еще одна проблема, с которой я сталкивался в при попытке обогнуть очень долго плавает до небольшого количества цифр.

Например, если у меня есть номер, который имеет длину 1000 цифр, и я хочу, чтобы закруглить его п цифр, я должен сделать что-то вроде floor(num * 10^1000)/10^1000). Это не работает, потому что 10^1000 чрезвычайно велико. Решением этого было бы умножение и деление несколько раз с меньшими показателями.

+0

Только убедившись, что Я верну вопрос. Какое из двух: округление до цифры (относительная точность) или «округление до единицы» (абсолютная точность). Например. 'round (0.253e + 5,2digits) == 0.25e + 5' (относительный) vs' round (0.253e + 5, 100units) == 0.253e + 5) '? –

+0

@AdrianColomitchi Я говорю больше по строкам «0.0236», округленное до 3 цифр, возвращает '0.024', если это то, о чем вы говорите? – esote

+0

«Я на самом деле использую многоточие Boost для произвольно-прецизионных поплавков». Вы должны быть более конкретными, чем это. – Veedrac

ответ

1

[Отредактировано - лучшее решение]

Выполнение округление может идти на основе:

round(x, precision_unit)=trunc(x/precision_unit+0.5)*precision_unit; 

Что-то вроде:

using namespace boost::multiprecision; 

    const uint lower_prec_digits=28; 

    typedef number<cpp_dec_float<100>> higher_prec; 
    typedef number<cpp_dec_float<lower_prec_digits>> lower_prec; 

    const higher_prec eps_div= 
     std::numeric_limits< 
      number<cpp_dec_float<lower_prec_digits+1>> 
     >::epsilon() 
    ; 

    higher_prec pi(
    "3.1415926535" 
     "8979323846" 
     "2643383279" 
     "5028841971" 
     "6939937510" 
     "5820974944" 
     "5923078164" 
     "0628620899" 
     "8628034825" 
     "3421170679" 
); 

    lower_prec round_pie=lower_prec(trunc(pi/eps_div+0.5)*eps_div); 

    std::cout.precision(100); 
    std::cout << round_pie << std::endl << pi << std::endl; 

Результат:

3.1415926535897932384626433833 
3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068 
+0

Не используйте 'std :: endl', если вам не нужен дополнительный материал, который он делает. '' \ n'' заканчивает линию. –