IPB
ЛогинПароль:

 
 Ответить  Открыть новую тему 
> Деление с высокой точностью
сообщение
Сообщение #1


Perl. Just code it!
******

Группа: Пользователи
Сообщений: 4 100
Пол: Мужской
Реальное имя: Андрей

Репутация: -  44  +


Всем привет! Необходимо получить результат деления двух предположительно целых чисел не превышающих 100 с точностью до 1000 знаков после разделителя, пытаюсь нагуглить какие-либо алгоритмы, пока безуспешно. На форуме поиск деление+точность результатов тоже не дал sad.gif Буду рад любым подсказкам. !4.gif

добавлено: собственно деление столбиком никто не отменял)) туплю под вечер)

Сообщение отредактировано: klem4 -


--------------------
perl -e 'print for (map{chr(hex)}("4861707079204E6577205965617221"=~/(.{2})/g)), "\n";'
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #2


Уникум
*******

Группа: Пользователи
Сообщений: 6 823
Пол: Мужской
Реальное имя: Лопáрь (Андрей)

Репутация: -  159  +


Цитата(klem4 @ 11.04.2011 22:36) *
добавлено: собственно деление столбиком никто не отменял)) туплю под вечер)
хихи)) разве это вечер? smile.gif я туплю обычно по утрам ))

На этот раз скорость не играет большой роли?
Где-то у меня была арифметика для чисел любой длины в любой СС, причем как целая так и дробная. Надо пошукать - мож, для FAQ сгодится..


--------------------
я - ветер, я северный холодный ветер
я час расставанья, я год возвращенья домой
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #3


Perl. Just code it!
******

Группа: Пользователи
Сообщений: 4 100
Пол: Мужской
Реальное имя: Андрей

Репутация: -  44  +


Да, скорость в данном случае мне не важна, намалевал на скорую руку(крайне не оптимизировано и не красиво), но может кому пригодится, работает без учета округления (так нужно было для решаемой мной задачи), то есть
1 / 200 = 0.005, с точностью до двух знаков результат работы функции = '0.00'.


// точность дробной части числа заданного в стороке s
int get_accuracy( std::string s )
{
size_t dot_pos = s.find(".");

if ( dot_pos == std::string::npos )
return 0;

return s.size() - (int)dot_pos - 1;
}

std::string complete( std::string s, int accuracy, int cur_accur )
{
if ( cur_accur == accuracy )
return s;

if ( cur_accur == 0 )
{
s += ".";
}

while ( cur_accur < accuracy )
{
s += "0";
++cur_accur;
}

while ( cur_accur > accuracy )
{
s.erase(s.length() - 1, 1);
--cur_accur;
}

if ( s[s.length() - 1] == '.' )
{
s.erase(s.length() - 1, 1);
}

return s;
}

std::string divide(int n, int m, std::string result, int accuracy, int iteration )
{
//std::cout << "CALL " << n << "/" << m << std::endl;

int cur_accur = get_accuracy(result);
if ( (iteration > 1000 ) || (n == 0) || ( (accuracy > 0) && (accuracy <= cur_accur) ) )
{
// some actions
return complete(result, accuracy, cur_accur );
}

int add_zero = 0;
while ( n < m )
{
n *= 10;
// if ( n < m )
++add_zero;
}

//std::cout << "add_zero = " << add_zero << std::endl;

if ( add_zero > 0 )
{
// у числа нету дробной части
if ( cur_accur == 0 )
{
// у числа нету Целой части
if ( result.length() == 0 )
{
result = "0.";
--add_zero;
}
else
{
result += ".";
--add_zero;
}
}
else
{
--add_zero;
}

while ( add_zero-- > 0 )
{
result += "0";
}
}

int int_part = n / m;
int T = int_part;
std::string str_part = "";

while ( T > 0 )
{
str_part = (char)((int)'0' + T % 10) + str_part;
T /= 10;
}

//std::cout << "STR_PART = " << str_part << std::endl;

result += str_part;
n -= int_part * m;

return divide(n, m, result, accuracy, iteration + 1 );
//return result;
}



вызов

int n, m, k;
std::cin >> n >> m >> k;
std::cout << divide(n, m, "", k, 0) << std::endl; // n / m с точностью k знаков после разделителя



--------------------
perl -e 'print for (map{chr(hex)}("4861707079204E6577205965617221"=~/(.{2})/g)), "\n";'
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 




- Текстовая версия 22.02.2018 19:31
Хостинг предоставлен компанией "Веб Сервис Центр" при поддержке компании "ДокЛаб"