Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Разбиение на цифры чисел long double

10K
04 декабря 2006 года
Omega Red
49 / / 15.10.2006
Вот задача: напечатать все цифры числа 1!+2!+…+100!
Кажется всё просто, но проблема в том, что для чисел long double недопустима операция % (нахождение остатка). Есть ли целые типы больше long, или какой есть другой способ?
Код:
#include "iostream.h"
 
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;
    }
}
63
04 декабря 2006 года
Zorkus
2.6K / / 04.11.2006
В числе 100! сотни цифр. Используй алгоритмы длинной арифметики.
У меня есть приличная статья по этой теме, полметра весит в pdf, кинуть?
10K
04 декабря 2006 года
Omega Red
49 / / 15.10.2006
Про алгоритмы длинной арифметики не знаю, поэтому от статьи не откажусь. Сбрасывай на webfile.ru, или лучше электронный ящик сказать?
63
04 декабря 2006 года
Zorkus
2.6K / / 04.11.2006
Да, лучше мыло скажи.
10K
04 декабря 2006 года
Omega Red
49 / / 15.10.2006
[email]reinwolf@mail.ru[/email]
10K
04 декабря 2006 года
Omega Red
49 / / 15.10.2006
Файл у тебя для Си? А то я в Паскале совсем не разбираюсь, в школе не проходили.
263
04 декабря 2006 года
koltaviy
816 / / 16.12.2004
Цитата: Zorkus
В числе 100! сотни цифр. Используй алгоритмы длинной арифметики.
У меня есть приличная статья по этой теме, полметра весит в pdf, кинуть?


?? Кинь мне тоже, пжлста!!:):
[EMAIL="koltaviy@mail.ru"]koltaviy@mail.ru[/EMAIL]

242
04 декабря 2006 года
Оlga
2.2K / / 04.02.2006
Цитата:
Кажется всё просто, но проблема в том, что для чисел long double недопустима операция %


с выделением целой части числа(если забыть о длинной арифметики) проблем быть не должно:

 
Код:
long double n = 123.4563;
long int temp = (long int)n;

если известно кол-во цифр после точек - тоже проблем нет:
 
Код:
long double n = 123.456;
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]
63
05 декабря 2006 года
Zorkus
2.6K / / 04.11.2006
koltaviy, Omega Red - отправил. Есть замечания по ней - пишите в аську. Файд на С++, там много того что щас можно используя библиотеки разные, переписать короче, но мне кажется, все написано нормально, большинство алгоритмов я писал - все рабочее.
3
05 декабря 2006 года
Green
4.8K / / 20.01.2000
Небольшое замечание по алгоритму.
Каждый раз ты считаешь факториал рекурсивно от n до 0.
Это нерационально.
Применив принцип динамического программирования ты на порядки (!) увеличишь производительность и упростишь алгоритм.
Для этого достаточно лишь использовать значение вычисленное на предыдущем шаге:
 
Код:
prevValue = 1;
    for (i = 1; i <= 100; i++)
    {
        prevValue *= i;
        sum += prevValue;
    }

это, собствоенно, весь алгоритм твоей задачи
63
05 декабря 2006 года
Zorkus
2.6K / / 04.11.2006
В принципе ты прав, но, насколько я помню, __int64 берет факториал до 19 включительно или около того. Так что твое замечание нужно просто обобщить, так сказать, на длинные числа.
10K
05 декабря 2006 года
Omega Red
49 / / 15.10.2006
Такс, научился складывать два длинных числа. Скоро научусь умножать.
Как тогда делать?
Код:
struct BigInt
{
    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;}
}
63
05 декабря 2006 года
Zorkus
2.6K / / 04.11.2006
Я недавно (около года назад) писал простенькую работу - вычисление экспоненты с заданной точностью (поспорил с преподом по инфе, какая точность у встроеных трансцендентных функций, когда разобрались, он предложил написать, я согласился).
Привожу код, может, какие-то приемы оттуда почерпнешь, комменты как мог писал. Там могут быть ошибки, тогда я плохо писал:(
Возможность медленности работы объясню подробно, если надо, и укажу, как исправить без потери качества для данной точности.
P.S. Писал в MinGWStudio, если тоже в ней будешь компилить - перед началом переименуй exp - файл в main, я забыл:)
10K
05 декабря 2006 года
Omega Red
49 / / 15.10.2006
Написал я эту прогу, только есть одна проблема. Вот два скрина, на первом код, на втором результаты. Как видно, 12 одинаковых строк с разными элементами дают правильный результат, а в цикле for почему-то неправильно...
http://img145.imageshack.us/img145/9448/factorialfa9.gif
http://img145.imageshack.us/img145/9540/resultsdy6.gif
10K
05 декабря 2006 года
Omega Red
49 / / 15.10.2006
Файл не скачивается с форума, Доунлоад Мастер какую-то страницу с авторизацией качает.
63
05 декабря 2006 года
Zorkus
2.6K / / 04.11.2006
Да все там нормально качается, только что для проверки скачал.
10K
05 декабря 2006 года
Omega Red
49 / / 15.10.2006
Всё-таки я сам разобрался. Вот в чём преимущество структурного программирования над объектным. Вместо фора лучше рекурсивную функцию использовать.
У меня как-то не хочет качаться. У тебя моё мыло осталось? Сбрасывай это решение и ещё некоторые на Си, которых тебе не жалко.
242
06 декабря 2006 года
Оlga
2.2K / / 04.02.2006
Цитата:
Всё-таки я сам разобрался. Вот в чём преимущество структурного программирования над объектным. Вместо фора лучше рекурсивную функцию использовать.


просветите меня плиз: что в ООП нельзя рекурсию использовать? :red:

309
06 декабря 2006 года
el scorpio
1.1K / / 19.09.2006
Просветите меня, а что мешает преобразовать число в строку, а потом рассматривать её посимвольно ? :D
242
06 декабря 2006 года
Оlga
2.2K / / 04.02.2006
Цитата: el scorpio
Просветите меня, а что мешает преобразовать число в строку, а потом рассматривать её посимвольно ? :D


а есть функция для float/double как itoa(), я чес слово не помню =).

10K
06 декабря 2006 года
Omega Red
49 / / 15.10.2006
Про что это вы говорите, не понимаю.
Что я могу сказать, так то, что если преобразовывать числа в строку, потом рассматривать каждый символ как число, складывать, так легче число как структуру представить.
Может быть в ООП можно вызывать функции, но работает это плохо, вот почему Паскаль проклятый язык, а на С++ пишутся почти все программы.
242
06 декабря 2006 года
Оlga
2.2K / / 04.02.2006
Цитата:
Может быть в ООП можно вызывать функции, но работает это плохо, [COLOR=blue]вот почему Паскаль проклятый язык[/COLOR], [COLOR=seagreen]а на С++ пишутся почти все программы[/COLOR].



кто то из нас двоих бредит. хелп :)

10K
06 декабря 2006 года
Omega Red
49 / / 15.10.2006
Книжка по Паскалю занимает 100 страниц, в то время как на С++, написана хотя бы одна игра, потому что видел в ошибке название функции и класса.
63
06 декабря 2006 года
Zorkus
2.6K / / 04.11.2006
Цитата: el scorpio
Просветите меня, а что мешает преобразовать число в строку, а потом рассматривать её посимвольно ? :D


А откуда ты его возьмешь, число? 100! - это только длинная арифметика. Имхо, глупо часть чисел сразу писать в строку - а часть в число, работать с ним, и потом переводить в строку.
А насчет посимвольного парсинга строки - так есть вполне известный стиль решения таких задач, я во вложении показывал пример реализации функций для длинных чисел, зачем извращаться-то?;)

63
06 декабря 2006 года
Zorkus
2.6K / / 04.11.2006
Цитата: Omega Red

Может быть в ООП можно вызывать функции, но работает это плохо, вот почему Паскаль проклятый язык, а на С++ пишутся почти все программы.


Цитата: Omega Red

Книжка по Паскалю занимает 100 страниц, в то время как на С++, написана хотя бы одна игра, потому что видел в ошибке название функции и класса.


Без комментариев:)
[QUOTE=OlgaKr]
кто то из нас двоих бредит. хелп [/QUOTE]
Никто не бредит, ты здорова, а парень просто не понял -видимо НЕ будем за это судить, но, Omega Red , ЧИТАЙ, ЗАПОЕМ!!!!!!!
Больно слышать:(

242
07 декабря 2006 года
Оlga
2.2K / / 04.02.2006
Цитата:
Больно слышать:(


[offtop] думала крыша едет :-) [/offtop]

2Omega Red
насколько я понимаю, ты на С++ пишешь, так С++ именно и поддерживает объектную модель программирования, которая вовсе не исключает использование функций(без них вообще невозможно) и рекурсии. хотя естественно, что на С++ можно написать программы основанные на структурной модели, как и на любом(известном мне) языке поддерживающем ООП, но не наоборот.

309
07 декабря 2006 года
el scorpio
1.1K / / 19.09.2006
Omega Red
С машинной точки зрения, между вызовом метода и вызовом функции разница очень маленькая.

Zorkus
И причём тут "длинная арифметика" - ведь для хранения числа используется long double, который прекрасно обрабатывается функцией FloatToStr (модуль "Math.hpp" из VCL) или аналогичными функциями модуля "math.h".

Единственный недостаток - вывод числа в экспотенциальной форме и "потеря значимости" - но это уже ограничения на длину "действительной части" чисел с плавающей точкой.

P.S. А почему алгоритмы "длинной арифметики" не имеют функций преобразования числа в текст (массив символов)?
Или всё-таки имеют? Тогда пользуйтесь на здоровье - зачем алгоритм определения цифр по второму разу придумывать :D
63
07 декабря 2006 года
Zorkus
2.6K / / 04.11.2006
Цитата: el scorpio

И причём тут "длинная арифметика" - ведь для хранения числа используется long double, который прекрасно обрабатывается функцией FloatToStr (модуль "Math.hpp" из VCL) или аналогичными функциями модуля "math.h".


А при чем тут long double? Сказано в условии - найти сумму факториалов от 1 до 100, что - факториал может быть дробным числом?
Это просто автор решил его сюда приплести, потому что решил, что его спасет мантисса огромная, но зачем повторять заблуждение?

Цитата: el scorpio

Единственный недостаток - вывод числа в экспотенциальной форме и "потеря значимости" - но это уже ограничения на длину "действительной части" чисел с плавающей точкой.


Да мелочь - правда, предложенное выражение содержит навскидку, цифр 175 - 190, а точность LD - 19-20...
И потом, длинная арифметика позволяет и дробные числа обрабатывать прекрасно.

Цитата: el scorpio

P.S. А почему алгоритмы "длинной арифметики" не имеют функций преобразования числа в текст (массив символов)?
Или всё-таки имеют? Тогда пользуйтесь на здоровье - зачем алгоритм определения цифр по второму разу придумывать :D


По второму разу придумываешь ты, причем что-то очень странное. Число в строку - это так в школах показывают иногда как пример нестандартного подхода. А как насчет использования в качестве основнания чисел, отличных от 10, например? Тебе не нужно эту информацию будет хранить? Я советую Окулова почитать, "Программирование в алгоритмах", или ту статью, что у меня тут спрашивали.
Вообще говоря, раз уж зашла речь про long double, то для приближенных вычислений факториалов можно и апроксимацию Стирлинга использовать, и погрешность будет невелика, но просто сама задача - самая что ни на есть олимпиадная, причем бородатая, если это слово применимо к задаче:)

10K
07 декабря 2006 года
Omega Red
49 / / 15.10.2006
Вот я заметил, что арифметика длинных чисел не может считать факториалы больше 160, хотя мой друг смог найти все числа 2000! на Дельфи. Можно ли на Си написать аткое число?
63
07 декабря 2006 года
Zorkus
2.6K / / 04.11.2006
Цитата: Omega Red
Вот я заметил, что арифметика длинных чисел не может считать факториалы больше 160, хотя мой друг смог найти все числа 2000! на Дельфи. Можно ли на Си написать аткое число?


1. Не поверю, что есть что-то такое, что можно написать на дельфе и нельзя на С++. Никогда:)
2. Что значит не может??? вылетает по неловленому эксепшену, виснет, выдает экран смерти? Можно сосчитать и до 10 000, думаю - просто вопрос времени. Код давай.

3
07 декабря 2006 года
Green
4.8K / / 20.01.2000
Цитата: Zorkus

Число в строку - это так в школах показывают иногда как пример нестандартного подхода.


Я бы руки отрывал за такой "нестандартный подход" :)

63
08 декабря 2006 года
Zorkus
2.6K / / 04.11.2006
Цитата: Green
Я бы руки отрывал за такой "нестандартный подход" :)


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

309
08 декабря 2006 года
el scorpio
1.1K / / 19.09.2006
Это я к чему - если есть модуль с "длинной арифметикой", то в этом модуле должны быть функции перевода "длинного" числа в строку - используйте их.
В противном случае - это плохой модуль, так как сразу возникает проблема отображения и вывода таких чисел :D
63
08 декабря 2006 года
Zorkus
2.6K / / 04.11.2006
Цитата: el scorpio
Это я к чему - если есть модуль с "длинной арифметикой", то в этом модуле должны быть функции перевода "длинного" числа в строку - используйте их.
В противном случае - это плохой модуль, так как сразу возникает проблема отображения и вывода таких чисел :D



Да, конечно, они там и есть.

10K
11 декабря 2006 года
Omega Red
49 / / 15.10.2006
Вот мой код:
Код:
#include "iostream.h"
#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 считает легко.
63
11 декабря 2006 года
Zorkus
2.6K / / 04.11.2006
1. В чем ты это писал, интересно, код этот вообще не компилится.
2. Функции max и min - на будущее, они есть в стандартной библиотеке, ее надо знать хоть немного.
2. Тебе же Green сказал общий алгоритм, зачем ты рекурсию стал писать? Навскидку исправил так
Код:
#include "iostream"
#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;
    /*&#196;&#235;&#232;&#237;&#224; &#235;&#254;&#225;&#238;&#227;&#238; &#247;&#232;&#241;&#235;&#224; &#240;&#224;&#226;&#237;&#224; 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, и не забудь константы длины правильно выставить в моем коде, и будет работать.
10K
12 декабря 2006 года
Omega Red
49 / / 15.10.2006
У меня кстати твой код не компилируется. У меня Visual C++ 6.0
А факториал через фор не работает. Вот в мэйн добавил:
Код:
void main()
{
    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
От чего это может быть?
63
13 декабря 2006 года
Zorkus
2.6K / / 04.11.2006
Цитата: Omega Red
У меня кстати твой код не компилируется. У меня Visual C++ 6.0.


Плохо, что 6-я. ставь 8. Или gcc...

Цитата: Omega Red

А факториал через фор не работает. Вот в мэйн добавил:
От чего это может быть?


Давай код целиком.

10K
13 декабря 2006 года
Omega Red
49 / / 15.10.2006
В универе на всех компах 6-ая версия, поэтому и я пишу на этой. А 8-ая многим лучше? И что лучше: 2005 или 8.0? Я в 2005 даже не смог найти "Выполнить"...
Код:
#include "iostream.h"
#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;
}
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог