Здравствуйте, SuperSuperMan, Вы писали:
Великолепно!
Вы только что подтвердили необходимость введения нового понятия и новой синтаксической конструкции. Вы использовали новое понятие
прибавить единицу и новую конструкцию «+». Осталось сделать ещё пару шагов в область метапрограммирования (или усложнения исходного языка) и золотой ключик у нас в кармане:
1, пока(меньше N) +
Сложность (длина) этой программы просто O(log(N)) в позиционной системе и O(N) в непозиционной. (Для записи числа N нужно место пропорциональное O(…).)
С такой задачей и один SuperSuper-программист обычно справиться, а вот просто программист ежедневно пишущий короткие чисто числовые программы (на вышеприведённых языках) засомневается, как реализовано «пока», «меньше» и «+». Для него это сложно, он привык просто к числам. В этом смысле очень показателен опыт eao197 (а это, судя по рейтингу и отзывам коллег, один из лучших программистов на RSDN):
Топик: cpp\Compile-time вычисления: а оно вообще надо?
26.10.2005 12:23
eao197> … я не хочу писать такой код, который привел ты и Dmi_3. Я не хочу читать такой код. Я хочу держаться подальше от проектов, в которых есть такой код.
16.11.2005 23:25
eao197> Действительно, реализация оказалась не такой уж и сложной
А для меня пока сложно привести ссылки на дискуссию. Но это же просто?! Хотя если я начну со стека протоколов TCP-IP (а тем паче с устройства модема или сетевой карты) это может оказаться действительно сложно.
Простые методы вполне подходящие для программирования маленьких простых задач часто совсем не подходят для программирования больших и сложных. Мне, например, приходилось сталкиваться с такой ситуацией (в более сложном варианте):
big_uint
add(big_uint a, big_uint b)
{
for(big_uint i0=0;i0<b;++i0)
++a;
return a;
}
big_uint
mul(big_uint a, big_uint b)
{
big_uint x(0);
for(big_uint i0=0;i0<b;++i0)
x=add(x,a);
return x;
}
big_uint
pow(big_uint base, big_uint exponent)
{
big_uint x(1);
for(big_uint i0=0;i0<exponent;++i0)
x=mul(x,base);
return x;
}
Здесь используются только простые (для нас, но не для первобытных) понятия
«повторить N раз» и «прибавить единицу». Эта программа понятна практически любому. НО…
Профайлер покажет, что при использовании pow() сильно «тормозит» big_uint::operator++(). И это мягко сказано! А люди
с полной серьёзностью начнут его оптимизировать. Совет использовать алгоритм быстрого умножения Тоома-Кука не будет восприниматься, ибо этот алгоритм сложен. (Это объективно так. Можете сами посмотреть.)
Однако я не предлагаю использовать сложные методы и конструкции, если Вас удовлетворяет полученное решение. Всё зависит от задачи. Например, многие напишут такой код вычисления чисел Фибоначчи:
int
FibboExp(int n, int a=0,int b=1)
{
if(n<2) return n?b:a;
return FibboExp(n-1,a,b)+FibboExp(n-2,a,b);
}
Это решение прямо и просто отражает рекуррентную формулу F(N)=F(N-1)+F(N-2) но Вы вряд ли дождётесь результата вычисления FibboExp(45)
Вот более сложный вариант. Он использует технику запоминания промежуточных результатов. Его уже требуется понимать (или верить).
int
FibboLin(int n, int a=0,int b=1)
{
if(n==0) return a;
return FibboLin(n-1,b,a+b);
}
Если (для диапазона int) Вас удовлетворяет время его работы то нет смысла писать
int FiboLogSTD(int n,int& d){
if(n>=2){
int const x(FiboLogSTD(n/2,d));
if(n&1){
n=d;
d*=x+x+n;
n*=n;
n+=x*x;
}else{
n=d;
d=n*n+x*x;
n=x*(n+n-x);
}
}
return n;
}
int FiboLog(int n,int a=0,int b=1){
int f0(1);
int const f1(FiboLogSTD(n,f0));
return a*(f0-f1)+b*f1;
}
Несмотря на то, что время работы этого алгоритма O(log(n)).
Совсем другое дело, если мы начнём работать с большими числами. Там линейное время работы второго алгоритма может оказаться неприемлемым.
Абсолютно такие же рассуждения работают и во время написания программы. Если задача проста и ресурсов много – пишем наиболее просто, если сложна и ресурсов мало – сложно. Кстати, квалификацию и внутреннюю дисциплину программистов тоже можно рассматривать как ресурсы. Если их мало — Java, если много — C++. (ой сколько врагов я сейчас нажил этим передёргиванием!)
P.S.
Тема топика возникла как (мои) провокация и передёргивание (в духе eao197)
Мне казалось, что это привлечёт больше внимания к проблеме простоты\сложности.
Видимо я ошибся.