Перейти к содержанию
    

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

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 бит.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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}:

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Точнее говоря: там дальше больше область быстрой сходимости:  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: Да и тут ещё повысить точность нетрудно, просто удлинив эти макросы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...