Разбиение на цифры чисел long double
Кажется всё просто, но проблема в том, что для чисел long double недопустима операция % (нахождение остатка). Есть ли целые типы больше long, или какой есть другой способ?
long double factorial (int);
void cifra(long double);
int a[200], i;
void main()
{
long double sum;
for (i = 1; i <= 100; i++)
{
sum += factorial(i);
}
cifra (sum);
cout<<"Summa ravna "<<endl;
for (i = 0; i < 200; i++)
cout<<a;
cout<<endl;
}
long double factorial (int n)
{
if (n == 0) return 1;
return (n * factorial(n - 1));
}
void cifra(long double k)
{
int s = 0;
for (i = 199; i >= 0, k != 0; i--)
{
a = k%10;
k = (k - k%10)/10;
}
}
У меня есть приличная статья по этой теме, полметра весит в pdf, кинуть?
У меня есть приличная статья по этой теме, полметра весит в pdf, кинуть?
?? Кинь мне тоже, пжлста!!:):
[EMAIL="koltaviy@mail.ru"]koltaviy@mail.ru[/EMAIL]
с выделением целой части числа(если забыть о длинной арифметики) проблем быть не должно:
long int temp = (long int)n;
если известно кол-во цифр после точек - тоже проблем нет:
long int temp1 = (long int)n;
long int temp2 = (long int)((n-temp1)*1000); //выделяем 3 цифры после точки
a если неизвестно, то надо подумать.
http://algolist.manual.ru/maths/longnum.php
[COLOR=red]для кода тэги code пользуем, не quote.[/COLOR]
Каждый раз ты считаешь факториал рекурсивно от n до 0.
Это нерационально.
Применив принцип динамического программирования ты на порядки (!) увеличишь производительность и упростишь алгоритм.
Для этого достаточно лишь использовать значение вычисленное на предыдущем шаге:
for (i = 1; i <= 100; i++)
{
prevValue *= i;
sum += prevValue;
}
это, собствоенно, весь алгоритм твоей задачи
Как тогда делать?
{
int values[MAX_LENGTH];
int size;
} R, Mas[100];
............................
for (i = 0; i < 100; i++)
Mas = Factorial (i+1);
R = clear();
for (i = 0; i < 100; i++)
R += sum (R, Mas);
}
...................
BigInt Factorial(int n)
{
if (n == 0) (...T..=..1..) return T;
else {T = mult (n, Factorial (n-1));
return T;}
}
Привожу код, может, какие-то приемы оттуда почерпнешь, комменты как мог писал. Там могут быть ошибки, тогда я плохо писал:(
Возможность медленности работы объясню подробно, если надо, и укажу, как исправить без потери качества для данной точности.
P.S. Писал в MinGWStudio, если тоже в ней будешь компилить - перед началом переименуй exp - файл в main, я забыл:)
У меня как-то не хочет качаться. У тебя моё мыло осталось? Сбрасывай это решение и ещё некоторые на Си, которых тебе не жалко.
просветите меня плиз: что в ООП нельзя рекурсию использовать? :red:
а есть функция для float/double как itoa(), я чес слово не помню =).
Что я могу сказать, так то, что если преобразовывать числа в строку, потом рассматривать каждый символ как число, складывать, так легче число как структуру представить.
Может быть в ООП можно вызывать функции, но работает это плохо, вот почему Паскаль проклятый язык, а на С++ пишутся почти все программы.
кто то из нас двоих бредит. хелп :)
А откуда ты его возьмешь, число? 100! - это только длинная арифметика. Имхо, глупо часть чисел сразу писать в строку - а часть в число, работать с ним, и потом переводить в строку.
А насчет посимвольного парсинга строки - так есть вполне известный стиль решения таких задач, я во вложении показывал пример реализации функций для длинных чисел, зачем извращаться-то?;)
Может быть в ООП можно вызывать функции, но работает это плохо, вот почему Паскаль проклятый язык, а на С++ пишутся почти все программы.
Книжка по Паскалю занимает 100 страниц, в то время как на С++, написана хотя бы одна игра, потому что видел в ошибке название функции и класса.
Без комментариев:)
[QUOTE=OlgaKr]
кто то из нас двоих бредит. хелп [/QUOTE]
Никто не бредит, ты здорова, а парень просто не понял -видимо НЕ будем за это судить, но, Omega Red , ЧИТАЙ, ЗАПОЕМ!!!!!!!
Больно слышать:(
[offtop] думала крыша едет :-) [/offtop]
2Omega Red
насколько я понимаю, ты на С++ пишешь, так С++ именно и поддерживает объектную модель программирования, которая вовсе не исключает использование функций(без них вообще невозможно) и рекурсии. хотя естественно, что на С++ можно написать программы основанные на структурной модели, как и на любом(известном мне) языке поддерживающем ООП, но не наоборот.
С машинной точки зрения, между вызовом метода и вызовом функции разница очень маленькая.
Zorkus
И причём тут "длинная арифметика" - ведь для хранения числа используется long double, который прекрасно обрабатывается функцией FloatToStr (модуль "Math.hpp" из VCL) или аналогичными функциями модуля "math.h".
Единственный недостаток - вывод числа в экспотенциальной форме и "потеря значимости" - но это уже ограничения на длину "действительной части" чисел с плавающей точкой.
P.S. А почему алгоритмы "длинной арифметики" не имеют функций преобразования числа в текст (массив символов)?
Или всё-таки имеют? Тогда пользуйтесь на здоровье - зачем алгоритм определения цифр по второму разу придумывать :D
И причём тут "длинная арифметика" - ведь для хранения числа используется long double, который прекрасно обрабатывается функцией FloatToStr (модуль "Math.hpp" из VCL) или аналогичными функциями модуля "math.h".
А при чем тут long double? Сказано в условии - найти сумму факториалов от 1 до 100, что - факториал может быть дробным числом?
Это просто автор решил его сюда приплести, потому что решил, что его спасет мантисса огромная, но зачем повторять заблуждение?
Единственный недостаток - вывод числа в экспотенциальной форме и "потеря значимости" - но это уже ограничения на длину "действительной части" чисел с плавающей точкой.
Да мелочь - правда, предложенное выражение содержит навскидку, цифр 175 - 190, а точность LD - 19-20...
И потом, длинная арифметика позволяет и дробные числа обрабатывать прекрасно.
P.S. А почему алгоритмы "длинной арифметики" не имеют функций преобразования числа в текст (массив символов)?
Или всё-таки имеют? Тогда пользуйтесь на здоровье - зачем алгоритм определения цифр по второму разу придумывать :D
По второму разу придумываешь ты, причем что-то очень странное. Число в строку - это так в школах показывают иногда как пример нестандартного подхода. А как насчет использования в качестве основнания чисел, отличных от 10, например? Тебе не нужно эту информацию будет хранить? Я советую Окулова почитать, "Программирование в алгоритмах", или ту статью, что у меня тут спрашивали.
Вообще говоря, раз уж зашла речь про long double, то для приближенных вычислений факториалов можно и апроксимацию Стирлинга использовать, и погрешность будет невелика, но просто сама задача - самая что ни на есть олимпиадная, причем бородатая, если это слово применимо к задаче:)
1. Не поверю, что есть что-то такое, что можно написать на дельфе и нельзя на С++. Никогда:)
2. Что значит не может??? вылетает по неловленому эксепшену, виснет, выдает экран смерти? Можно сосчитать и до 10 000, думаю - просто вопрос времени. Код давай.
Число в строку - это так в школах показывают иногда как пример нестандартного подхода.
Я бы руки отрывал за такой "нестандартный подход" :)
Ага, вместо того чтобы Кормена преподавать и Кнута:). А потом те, кого так учили, пишут проги. А те, кто не вникает, в свою очередь, списывают глюки и тормоза на язык или платформу:(( обидно
В противном случае - это плохой модуль, так как сразу возникает проблема отображения и вывода таких чисел :D
В противном случае - это плохой модуль, так как сразу возникает проблема отображения и вывода таких чисел :D
Да, конечно, они там и есть.
#include "math.h"
const int BASE = 10, BASE_DIG = 1, MAX_LENGTH = 400;
int i;
struct BigInt
{
int values[MAX_LENGTH];
int size;
}R, result, Fact;
BigInt mainRes (int);
BigInt factorial (int);
BigInt sum(BigInt &, BigInt &);
BigInt mult2D(BigInt &, long);
int eval_length (BigInt &, int);
void clear (BigInt &);
void print (BigInt &);
int min(int, int);
int max(int, int);
void main()
{
clear(R);
/*R = mainRes (100);*/
R = factorial (300);
print(R);
}
BigInt mainRes (int k)
{
if (k == 1)
{
return factorial (1);
}
return sum (factorial (k), mainRes (k-1));
}
BigInt factorial(int n)
{
if (n == 0)
{
Fact.values[0] = 1;
Fact.size = 1;
return Fact;
}
return mult2D(factorial(n - 1), n);
}
BigInt sum(BigInt &A, BigInt &B)
{
clear(result);
int carry = 0;
int length = max(A.size, B.size) + 1;
for (i = 0; i < length; i++)
{
carry += A.values + B.values;
result.values = carry % BASE;
carry /= BASE;
}
result.size = eval_length (result, length);
return result;
}
BigInt mult2D(BigInt &A, long B)
{
clear(result);
int carry = 0;
/*Длина любого числа равна log10(B) + 1=> log10(726)+1 = 3*/
int length = A.size + (int)(log(B * 1.0)/log(BASE * 1.0)) + 1;
for (i = 0; i < length; i++)
{
carry += A.values * B;
result.values = carry % BASE;
carry /= BASE;
}
result.size = eval_length(result, length);
return result;
}
int eval_length (BigInt &A, int from)
{
int index = min (from, MAX_LENGTH - 1);
while (index > 0 && A.values[index] == 0)
index--;
return index + 1;
}
void clear (BigInt &A)
{
for (i = 0; i < MAX_LENGTH; i++)
A.values = 0;
A.size = 1;
}
void print (BigInt &A)
{
for (i = A.size - 1; i >= 0; i--)
cout<<A.values;
cout<<endl;
/* cout<<A.size<<endl;*/
}
int min(int a, int b)
{
if (a < b)
return a;
else return b;
}
int max (int a, int b)
{
if (a > b)
return a;
else return b;
}
Оно просто пишет Press any key to continue, хотя написано всвё правильно, факториал 150 считает легко.
2. Функции max и min - на будущее, они есть в стандартной библиотеке, ее надо знать хоть немного.
2. Тебе же Green сказал общий алгоритм, зачем ты рекурсию стал писать? Навскидку исправил так
#include "cmath"
using namespace std;
const int BASE = 10, BASE_DIG = 1, MAX_LENGTH = 1000;
int i;
struct BigInt
{
int values[MAX_LENGTH];
int size;
}R, result, Fact;
BigInt mainRes (int);
BigInt factorial (int);
BigInt sum(BigInt A, BigInt B);
BigInt mult2D(BigInt A, int B );
int eval_length (BigInt &, int);
void clear (BigInt &);
void print (BigInt &);
int min(int, int);
int max(int, int);
int main()
{
clear(R);
//R = mainRes (100);
R = factorial (250);
print(R);
}
BigInt mainRes (int k)
{
if (k == 1)
{
return factorial (1);
}
return sum (factorial (k), mainRes (k-1));
}
BigInt factorial(int n)
{
if (n == 0)
{
Fact.values[0] = 1;
Fact.size = 1;
return Fact;
}
return mult2D(factorial(n - 1), n);
}
BigInt sum(BigInt A, BigInt B)
{
clear(result);
int carry = 0;
int length = max(A.size, B.size) + 1;
for (i = 0; i < length; i++)
{
carry += A.values + B.values;
result.values = carry % BASE;
carry /= BASE;
}
result.size = eval_length (result, length);
return result;
}
BigInt mult2D(BigInt A, int B)
{
clear(result);
int carry = 0;
/*Äëèíà ëþáîãî ÷èñëà ðàâíà log10(B) + 1=> log10(726)+1 = 3*/
int length = A.size + (int)(log(B * 1.0)/log(BASE * 1.0)) + 1;
for (i = 0; i < length; i++)
{
carry += A.values * B;
result.values = carry % BASE;
carry /= BASE;
}
result.size = eval_length(result, length);
return result;
}
int eval_length (BigInt &A, int from)
{
int index = min (from, MAX_LENGTH - 1);
while (index > 0 && A.values[index] == 0)
index--;
return index + 1;
}
void clear (BigInt &A)
{
for (i = 0; i < MAX_LENGTH; i++)
A.values = 0;
A.size = 1;
}
void print (BigInt &A)
{
for (i = A.size - 1; i >= 0; i--)
cout<<A.values;
cout<<endl;
/* cout<<A.size<<endl;*/
}
int min(int a, int b)
{
if (a < b)
return a;
else return b;
}
int max (int a, int b)
{
if (a > b)
return a;
else return b;
}
Зачем все усложнять, а потом говорить, что не работает?
3. Потому что в моем шаблоне стоит MAX_LENGTH = 400, число 150! ->262 знака, число 300! -> 614 знаков.
4. Для чисел больше 250 он, точно, не считает факториал. Учитывая, что ты используешь рекурсию в 2 местах, скорее всего стек переполняется.
(если действительно так, то вот нагляднейший пример для темы - как лучше вычислять факториал:D)
Напиши, как сказал Green, и не забудь константы длины правильно выставить в моем коде, и будет работать.
А факториал через фор не работает. Вот в мэйн добавил:
{
clear(Fact);
/*R = mainRes (100);*/
Fact.values[0] = 1;
Fact.size = 1;
for (i = 1; i < 4; i++)
{
Fact = mult2D(Fact, i);
}
print(Fact);
}
Оно неправильно работает: 1*3*3*3*3,
Если поставить от двух до 3, то 1*2*3*3*3
От чего это может быть?
#include "math.h"
const int BASE = 10, MAX_LENGTH = 1000;
int i;
struct BigInt
{
int values[MAX_LENGTH];
int size;
}R, result, Fact;
BigInt sum(BigInt &, BigInt &);
BigInt mult2D(BigInt &, int);
int eval_length (BigInt &, int);
void clear (BigInt &);
void print (BigInt &);
int min(int, int);
int max(int, int);
void main()
{
clear(Fact);
Fact.values[0] = 1;
Fact.size = 1;
for (i = 1; i < 4; i++)
{
Fact = mult2D(Fact, i);
}
print(Fact);
}
BigInt mult2D(BigInt &A, int B)
{
clear(result);
int carry = 0;
/*Длина любого числа равна log10(B) + 1=> log10(726)+1 = 3*/
int length = A.size + (int)(log(B * 1.0)/log(BASE * 1.0)) + 1;
for (i = 0; i < length; i++)
{
carry += A.values * B;
result.values = carry % BASE;
carry /= BASE;
}
result.size = eval_length(result, length);
return result;
}
int eval_length (BigInt &A, int from)
{
int index = min (from, MAX_LENGTH - 1);
while (index > 0 && A.values[index] == 0)
index--;
return index + 1;
}
void clear (BigInt &A)
{
for (i = 0; i < MAX_LENGTH; i++)
A.values = 0;
A.size = 1;
}
void print (BigInt &A)
{
for (i = A.size - 1; i >= 0; i--)
cout<<A.values;
cout<<endl;
/* cout<<A.size<<endl;*/
}
int min(int a, int b)
{
if (a < b)
return a;
else return b;
}
int max (int a, int b)
{
if (a > b)
return a;
else return b;
}