jcxz 240 11 апреля, 2022 Опубликовано 11 апреля, 2022 · Жалоба 33 минуты назад, VladislavS сказал: Как-то посчитать, конечно же, можно. Есть даже готовые библиотеки - gcem Но тут только и жди где ногу прострелишь. Зачем нам "библиотеки"? А школьный курс математики - на что? Взял первый попавшийся метод аппроксимации натурального логарифма (не оптимальный, просто первый попавшийся). И тупо, в лоб: #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 не потрачено! Чего так боялся ТС. Всё исключительно - силами компилятора. PPS: Ранее здесь на форуме, я уже приводил свой подобный метод compile-time расчёта квадратного корня методом Ньютона-Рафсона. Там получилась точность ~30 бит. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladislavS 39 11 апреля, 2022 Опубликовано 11 апреля, 2022 · Жалоба Ага, и так по всему math.h НИР разводить :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
natsu 0 11 апреля, 2022 Опубликовано 11 апреля, 2022 · Жалоба 19 минут назад, VladislavS сказал: Ага, и так по всему math.h НИР разводить :) И по всем диапазонам значений. double const tableLN[] = {LN(2), LN(10), LN(50), LN(100), LN(300), LN(500), LN(700), LN(1000)}; 2 0,693147181 10 2,302585093 50 3,912023005 100 4,605170186 300 5,703782475 500 6,214608098 700 6,551080335 1000 6,907755279 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 240 11 апреля, 2022 Опубликовано 11 апреля, 2022 · Жалоба 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}: А как перейти к другим диапазонам - думайте сами. Не всю же жизнь чужим умом жить. Тем более что переход там элементарный. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
natsu 0 11 апреля, 2022 Опубликовано 11 апреля, 2022 · Жалоба С таким подходом надо откладывать основную работу и садиться писать свою библиотеку. В любом случае за идею спасибо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 240 11 апреля, 2022 Опубликовано 11 апреля, 2022 · Жалоба Точнее говоря: там дальше больше область быстрой сходимости: 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: Да и тут ещё повысить точность нетрудно, просто удлинив эти макросы. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться