Комментарии 24
1) «заколотало», «чисельные», «додаём» — о значении некоторых перлов вашего новояза остаётся только догадываться, и то безуспешно. Установите в браузер проверку орфографии, пожалуйста. Мне больно за читателей и других форумов, в которые вы пишете, причём чаще, чем на Хабре.
2) способы проигнорировать функцию main() при выполнении программы существуют, да.
3) Вводная по метапрограммированию — тоже любопытна.
2) способы проигнорировать функцию main() при выполнении программы существуют, да.
3) Вводная по метапрограммированию — тоже любопытна.
Читать Майерса и Александреску это хорошо. Но я бы за такие развлечения в коде проекта без явно указанной необходимости в таком коде, отрывал руки без права пришития обратно.
Шаблоны очень сложны в отладке и сообщения об ошибках выдаваемые gcc на шаблонах не страдают информативностью. Подобный код хорош, когда он написан раз и его трогать больше не надо. Или когда действительно встаёт задача какие-то вещи для оптимизации вынести в compile-time. В остальном — такой код — лютое нечитабельное и неподдерживаемое говно.
Я не говорю про то, что шаблоны это плохо, но вот к метапрограммированию на них надо относиться очень аккуратно.
Шаблоны очень сложны в отладке и сообщения об ошибках выдаваемые gcc на шаблонах не страдают информативностью. Подобный код хорош, когда он написан раз и его трогать больше не надо. Или когда действительно встаёт задача какие-то вещи для оптимизации вынести в compile-time. В остальном — такой код — лютое нечитабельное и неподдерживаемое говно.
Я не говорю про то, что шаблоны это плохо, но вот к метапрограммированию на них надо относиться очень аккуратно.
Ну что вы, теперь так e вычисляить уже не модно!
Вот он, новый способ:
Вот он, новый способ:
#include <iostream>
constexpr int factorial(int n)
{
return n > 1? factorial(n-1) * n : 1;
}
constexpr double cpow(double v, int n)
{
return n ==0? 1: v * cpow(v, n-1);
}
constexpr double factor(double v, int n)
{
return cpow(v, n) / factorial(n);
}
constexpr double sum(double v, int n, int max)
{
return factor(v, n) + (max == n? 0: sum(v, n + 1, max));
}
constexpr double cexp(double v, int accuracy)
{
return sum(v, 0, accuracy);
}
int main(int argc, const char** argv)
{
constexpr double e = cexp(1, 8);
std::cout.precision(15);
std::cout << e << "\n";
}
От непосредственного вычисления значения факториала можно избавиться путем выражения последующего члена ряда Тейлора через предыдущий. Насколько я помню, могу ошибаться, fpu так и вычисляет тригонометрию.
Насчет тригонометрии — вроде давно таблицы Брадиса во флэше записаны, вычислять только поправку нужно.
У вас неправильная сумма ряда. Вот результат на Maple:
2.7182818284590452353602874713526624977572470937000 — точное значение:
2.7182818284590452353602874713526624976385970411899 — Ряд Тейлора до 1/32!
Цепную дробь пока не посчитал.
2.7182818284590452353602874713526624977572470937000 — точное значение:
2.7182818284590452353602874713526624976385970411899 — Ряд Тейлора до 1/32!
Цепную дробь пока не посчитал.
2.7182818284590452353602874713558030927124686274627 — цепная дробь (33 члена разложения)
Зато если считать в рациональных числах (не сокращая их) и ограничивать числитель и знаменатель какой-нибудь константой, то цепные дроби дадут почти вдвое лучший результат по числу знаков. Так, если взять ограничение 2^32, то цепную дробь можно считать до [...,14,1,1], и получается 848456353/312129649 (17 верных знаков). Ряд Тейлора считается до 1/12!, и получается 1302061345/479001600 (9 верных знаков). Удивительно, что сумма обратных факториалов иногда сокращается.
— сейчас я покажу вам особую, шаблонную магию!
— в рот мне ноги! нет-нет-нет, александреску, немедленно верни все как было!!!
— в рот мне ноги! нет-нет-нет, александреску, немедленно верни все как было!!!
Не обращайте внимания на граммар-нази и лиц, лишенных чувства юмора. Статья здоровская! Только напишите в начале крупными буквами «Не пытайтесь повторить это в реальных проектах»:)
Почему статья не в хабе «Ненормальное программирование». Требую перенести!
Шаблоны в С++ это как подъязык в языке. Т.е. сейчас вы решили задачу поиска экспоненты на специфическом языке, а не на С++. Статья хорошая в плане того, что бы взять на заметку и когда приспичит писать шаблоны, посмотреть и вспомнить как можно извратиться :)
Шаблоны в С++ это как подъязык в языке. Т.е. сейчас вы решили задачу поиска экспоненты на специфическом языке, а не на С++. Статья хорошая в плане того, что бы взять на заметку и когда приспичит писать шаблоны, посмотреть и вспомнить как можно извратиться :)
Думаю, именно из-за такого безобразия в метапрограммировании на шаблонах Александреску и сбежал в D.
Compile-time аналог на D (используя цепную дробь):
D упрощает compile-time программирование, а люди идут в своих извращениях дальше: compile-time raytracer.
Compile-time аналог на D (используя цепную дробь):
module ecompute;
import std.stdio;
// Вариант 1, используя CTFE
static double computeE1(int n)
{
double innerCompute(int i, int m)
{
if(m <= 0)
{
return 0.0;
}
return 1.0/(
1.0 + 1.0/(
i + 1.0/(
1.0 + innerCompute(i + 2, m - 1))));
}
return 2.0 + innerCompute(2, n);
}
// Вариант 2, олдскул
template computeE2(int n)
{
private template innerCompute(int i, int m)
{
static if(m <= 0)
{
enum innerCompute = 0.0;
} else
{
enum innerCompute = 1.0/(
1.0 + 1.0/(
i + 1.0/(
1.0 + innerCompute!(i + 2, m - 1))));
}
}
enum computeE2 = 2.0 + innerCompute!(2, n);
}
void main()
{
// Вариант 1
static immutable e1 = computeE1(20);
pragma(msg, e1);
printf("Case 1, e = %1.20f \n",e1);
// Вариант 2
static immutable e2 = computeE2!(20);
pragma(msg, e2);
printf("Case 2, e = %1.20f \n",e2);
}
D упрощает compile-time программирование, а люди идут в своих извращениях дальше: compile-time raytracer.
Я тоже около 15 лет думал, что пишется «substract». Так и писал. А оказалось — «subtract». Видимо, это какое-то популярное заблуждение.
Неа, и то и то правильно. Но substract — устаревшая форма.
en.wiktionary.org/wiki/substract
english.stackexchange.com/questions/3640/is-substract-versus-subtract-a-proper-word
Сейчас предпочтительнее юзать subtract. А вот почему многие(и я, в том числе) юзают именно substract — тот еще вопрос.
en.wiktionary.org/wiki/substract
english.stackexchange.com/questions/3640/is-substract-versus-subtract-a-proper-word
Сейчас предпочтительнее юзать subtract. А вот почему многие(и я, в том числе) юзают именно substract — тот еще вопрос.
Возможно стоит добавить следующие ссылки:
Template metaprogramming на википедии
Boost.MPL — фреймворк для создания программ, которые производят вычисления во время компиляции с помощью шаблонов.
Template metaprogramming на википедии
Boost.MPL — фреймворк для создания программ, которые производят вычисления во время компиляции с помощью шаблонов.
Ох, я тоже что-то подобное тут писал =)
habrahabr.ru/post/124963/
habrahabr.ru/post/124963/
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Вычисляем значение числа e на этапе компиляции