Jump to content
    

как избавиться от предупреждений компилятора

33 минуты назад, VladislavS сказал:

Как-то посчитать, конечно же, можно. Есть даже готовые библиотеки - gcem

Но тут только и жди где ногу прострелишь.

Зачем нам "библиотеки"? А школьный курс математики - на что?  :wink:

Взял первый попавшийся метод аппроксимации натурального логарифма (не оптимальный, просто первый попавшийся). И тупо, в лоб:

#define LN_CALC_X(x) (((x) - 1.) / ((x) + 1))
#define LNi(x, y, i) (LN_CALC_X(x) / i + LN_CALC_X(x) * LN_CALC_X(x) * (y))
#define LN(x) (2 * LNi(x, LNi(x, LNi(x, LNi(x, LNi(x, LNi(x, LNi(x, LNi(x, LNi(x, LNi(x, LNi(x, LNi(x, LNi(x, LNi(x, LN_CALC_X(x) / 29, 27), 25), 23), 21), 19), 17), 15), 13), 11), 9), 7), 5), 3), 1))

Макрос LN() - compile-time расчёт натурального логарифма.

Построим таблицу значений для диапазона x = {1/exp(1) ... 1}:

__root float const tableLN[] = {LN(1), LN(.9), LN(.8), LN(.7), LN(.6), LN(.5), LN(.4), LN(0.368)};

Смотрим содержимое tableLN под отладчиком (через IAR-овский листинг к сожалению не получится):

Expression  Value Location  Type
tableLN <array> 0x20000AA0  float[8]
[0] 0.0               0x20000AA0  float
[1] -1.0536051544E-1  0x20000AA4  float
[2] -2.23143547E-1    0x20000AA8  float
[3] -3.5667493933E-1  0x20000AAC  float
[4] -5.10825634E-1    0x20000AB0  float
[5] -6.9314718244E-1  0x20000AB4  float
[6] -9.1629076E-1     0x20000AB8  float
[7] -9.9967235322E-1  0x20000ABC  float

Как видно - достаточно точно получилось. Если взять более оптимальный метод (быстрее сходящийся), то, думаю, можно и ещё точнее получить. Какого-нить Ньютона-Рафсона к примеру...

 

PS: И ни одного драгоценного такта в run-time не потрачено! Чего так боялся ТС. Всё исключительно - силами компилятора.  :biggrin:

PPS: Ранее здесь на форуме, я уже приводил свой подобный метод compile-time расчёта квадратного корня методом Ньютона-Рафсона. Там получилась точность ~30 бит.

Share this post


Link to post
Share on other sites

Ага, и так по всему math.h НИР разводить :)

Share this post


Link to post
Share on other sites

19 минут назад, VladislavS сказал:

Ага, и так по всему math.h НИР разводить :)

И по всем диапазонам значений.

 

double const tableLN[] = {LN(2), LN(10), LN(50), LN(100), LN(300), LN(500), LN(700), LN(1000)};

220411160220175.png.ba0a0033fb77bd3546fbf8f248028b82.png

2 0,693147181
10 2,302585093
50 3,912023005
100 4,605170186
300 5,703782475
500 6,214608098
700 6,551080335
1000 6,907755279

Share this post


Link to post
Share on other sites

13 минут назад, natsu сказал:

И по всем диапазонам значений.

double const tableLN[] = {LN(2), LN(10), LN(50), LN(100), LN(300), LN(500), LN(700), LN(1000)};

Читайте внимательнее. Я написал, что этот метод достаточно точен для диапазона:

41 минуту назад, jcxz сказал:

Построим таблицу значений для диапазона x = {1/exp(1) ... 1}:

А как перейти к другим диапазонам - думайте сами. Не всю же жизнь чужим умом жить.

Тем более что переход там элементарный.

Share this post


Link to post
Share on other sites

С таким подходом надо откладывать основную работу и садиться писать свою библиотеку.

В любом случае за идею спасибо.

Share this post


Link to post
Share on other sites

Точнее говоря: там дальше больше область быстрой сходимости:  x = {1/exp(1) ... exp(1)}

 

19 минут назад, natsu сказал:

С таким подходом надо откладывать основную работу и садиться писать свою библиотеку.

А чё тут писать? Через свойства логарифмов - всё просто:

#define EXP 2.71828182845904524
#define LNZ1(x) (((x) < EXP) ? 0: ((x) < EXP*EXP*EXP) ? 2: ((x) < EXP*EXP*EXP*EXP*EXP) ? 4: ((x) < EXP*EXP*EXP*EXP*EXP*EXP*EXP) ? 6: 8)
#define LNZ2(x) (((x) < EXP) ? (x): ((x) < EXP*EXP*EXP) ? (x) / (EXP*EXP): ((x) < EXP*EXP*EXP*EXP*EXP) ? (x) / (EXP*EXP*EXP*EXP): \
  ((x) < EXP*EXP*EXP*EXP*EXP*EXP*EXP) ? (x) / (EXP*EXP*EXP*EXP*EXP*EXP): (x) / (EXP*EXP*EXP*EXP*EXP*EXP*EXP*EXP))
#define LNXX(x) (LN(LNZ2(x))+LNZ1(x))

__root float const tableLN[] = {LNXX(1000), LNXX(3300), LNXX(8600), LNXX(15000), LNXX(22000)};

Даёт довольно хорошую точность для x = {1/exp(1) ... exp(10)}; т.е. - примерно до x=22000.

Если пересчитать все эти EXP*EXP*... в числа на калькуляторе, то может и ещё точнее будет.

 

PS: Да и тут ещё повысить точность нетрудно, просто удлинив эти макросы.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...