Russian Qt Forum
Ноябрь 27, 2024, 02:39 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: факториал числа не больше 12  (Прочитано 7304 раз)
PavelDart
Гость
« : Март 13, 2010, 01:46 »

Блин, мелочь, но не могу разобраться в чём загвоздка.


Код
C++ (Qt)
#include <math.h>
 
QString str2;
double t_otv,n;
 
void Form2::pb()
   {
   n=lineEdit10->text().toDouble();
   t_otv=fact(n);
   str2.setNum(t_otv);
   }
 
int Form2::fact(double n)
 {
 double ret=1;
 double zdoub;
 int j;
 
 zdoub=1;
   if (n==0)
ret=1;
   else
for(j=1; j<=n; j++)
   {
    ret=ret*zdoub;
    zdoub++;
           }
   return ret;
 }
 
 
 

при n>12 выдаёт -2.14748e+09 - чего явно не может быть.
Записан
KuZ
Гость
« Ответ #1 : Март 13, 2010, 02:04 »

Скорей всего, метод возвращает значение типа инт, у тебя оно не влазит. На дабл поменяй
Записан
hackoff
Гость
« Ответ #2 : Март 13, 2010, 04:42 »

а лучше  long double Улыбающийся
Записан
PavelDart
Гость
« Ответ #3 : Март 13, 2010, 06:38 »

Скорей всего, метод возвращает значение типа инт, у тебя оно не влазит. На дабл поменяй

Нашёл информацию, что можно поменять с помощью type_specifier function_name(type _argument);
куда прописывать - непонятно.

p.s. пишу в Designer
« Последнее редактирование: Март 13, 2010, 07:03 от PavelDart » Записан
zoro86
Гость
« Ответ #4 : Март 13, 2010, 08:41 »

так попробуй
double Form2::fact(double n)
  {
  double ret=1;
  double zdoub;
  int j;
 
  zdoub=1;
    if (n==0)
   ret=1;
    else
   for(j=1; j<=n; j++)
       {
        ret=ret*zdoub;
        zdoub++;
            }
    return ret;
  }
Записан
JayFOX
Гость
« Ответ #5 : Март 13, 2010, 10:31 »

Думаю, не стоить тратить столько строчек кода, хотя это непринципиально.
Код:
double f(double x)
{
    return x?f(x-1)*x:1;
}
Записан
MoPDoBoPoT
Гость
« Ответ #6 : Март 13, 2010, 13:41 »

Код:
double f(double x)
{
    return x?f(x-1)*x:1;
}
Во-первых, нет проверки на отрицательность аргумента, во-вторых, рекурсия здесь неуместна, это явно не тот случае, где она нужна. Рекурсию используют, где нельзя обойтись циклом или где без рекурсии будет "мега огород" (это я про императивные языки программирования, а не про логические/функциональные).
Или я старых книг начитался, и все не так (:
Записан
JayFOX
Гость
« Ответ #7 : Март 13, 2010, 14:22 »

Проверку на отрицательность можно сделать изменив тест на x>0, ну давайте тогда сделаем проверку на то что число натуральное)))
А про рекурсию - какой критерий её уместности, программист принимает решение какие средства ему использовать, и что плохого в том что она есть, конечно если стек вызовов искусственно ограничен.
Нету критериев "мега огород" и "явно неуместна", ИМХО конечно.
Записан
npkitsul
Гость
« Ответ #8 : Март 13, 2010, 15:12 »

Код:
double f(double x)
{
    return x?f(x-1)*x:1;
}
Во-первых, нет проверки на отрицательность аргумента,

Тогда  Строит глазки :
Код:
double f(double x)
{
    if (x < 0)
        return FALSE;
    return x?f(x-1)*x:1;
}

во-вторых, рекурсия здесь неуместна, это явно не тот случае, где она нужна. Рекурсию используют, где нельзя обойтись циклом или где без рекурсии будет "мега огород" (это я про императивные языки программирования, а не про логические/функциональные).
Или я старых книг начитался, и все не так (:

Парадоксально, но не так. Классическая и одна из первых оптимизаций в компиляторах, tail recursion elimination (http://en.wikipedia.org/wiki/Tail_recursion , http://www.cs.hamilton.edu/~bailey/pubs/techreps/TR-2001-2.pdf), автоматически преобразует эту рекурсию в цикл похожий на пример вверху.

 В замешательстве
Записан
SimpleSunny
Гость
« Ответ #9 : Март 13, 2010, 17:39 »

Парадоксально, но не так. Классическая и одна из первых оптимизаций в компиляторах, tail recursion elimination (http://en.wikipedia.org/wiki/Tail_recursion , http://www.cs.hamilton.edu/~bailey/pubs/techreps/TR-2001-2.pdf), автоматически преобразует эту рекурсию в цикл похожий на пример вверху.

Хвостовая рекурсия не входит в стандарт языка С++, поэтому компиляторы не обязаны ее поддерживать. А в следствии этого можно будет напороться на грабли в будущем: при переносе на другие платформы, при более сложном варианте, когда компилятор отчего-то не захочет оптимизировать, /etc. Поэтому в таких случаях разумней компилятору явно указывать, что будет цикл, а не рекурсия, тем самым облегчая себе жизнь в будущем.
Записан
npkitsul
Гость
« Ответ #10 : Март 13, 2010, 18:17 »

Хвостовая рекурсия не входит в стандарт языка С++, поэтому компиляторы не обязаны ее поддерживать. А в следствии этого можно будет напороться на грабли в будущем: при переносе на другие платформы,
Все неигрушечные компиляторы её поддерживают!!!
Притом в промежуточном коде (e.g. RTL в gcc) независящем от платформы.
Вот как в gcc: http://www.dis.com/gnu/gccint/Passes.html

при более сложном варианте, когда компилятор отчего-то не захочет оптимизировать, /etc. Поэтому в таких случаях разумней компилятору явно указывать, что будет цикл, а не рекурсия, тем самым облегчая себе жизнь в будущем.

Например врубив --debug  Улыбающийся, все или почти все оптимизации отключаются...
Записан
PavelDart
Гость
« Ответ #11 : Март 13, 2010, 19:59 »

так попробуй
double Form2::fact(double n)
 

Мда... ) Всё, как обычно, оказалось логично и просто.
По поводу рекурсии, согласен с тем, что при отсутствии ограничений на стек - предпочтительнее рекурсия.
Спасибо всем за помощь.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.181 секунд. Запросов: 21.