Как ввести логарифм по основанию

Ввод чисел:

Целые числа вводятся обычным способом, например: 4 ; 18 ; 56
Для ввода отрицательного числа необходимо поставить знак минус: −19 ; −45 ; −90
Рациональные числа вводятся с использованием символа / , например: 3 / 4 ; −5 / 3 ; 5 / (-19)
Вещественные числа вводятся с использованием точки в качестве разделителя целой и дробной частей: 4.5 ; −0.4

Ввод переменных и констант:

Переменные и константы вводятся латинскими буквами, например: x ; y ; z ; a ; b .
Константы π и e вводятся как pi и e — соответственно.
Символ бесконечности ∞ вводится двумя маленькими латинскими буквами oo или словом inf .
Соответственно, плюс бесконечность задается как +oo, и минус бесконечность как -oo.

Сумма и разность:

Сумма и разность задаются при помощи знаков + и — соответственно, например: 3 + a ; x + y ; 5 — 4 + t ; a — b + 4 ; ВНИМАНИЕ! Никаких пробелов между операндами быть не должно, например ввод: x + a — неправильный , правильно вводить так: x + a — без пробелов.

Умножение:

Умножение задается знаком * , например: 3 * t ; x * y ; −5 * x .
ВНИМАНИЕ! Ввод знака * необходим всегда, т.е. запись типа: 2 x — недопустима . Следует всегда использовать знак * , т.е правильная запись: 3 * x .

Деление:

Деление задается знаком / , например: 15 / a ; y / x ;.

Степень:

Степень задается знаком ^ , например: x ^ 2 ; 4 ^ 2 ; y ^ (-1 / 2) .

Приоритет операций:

Для указания (или изменения) приоритета операций необходимо использовать скобки () , например: ( a + b ) / 4 — тут вначале будет произведено сложение a + b , а потом сумма разделится на 4 , тогда как без скобок: — сначала b разделится на 4 и к полученному прибавится a . ВНИМАНИЕ! В непонятных случаях лучше всегда использовать скобки для получения нужного результата, например: 2 ^ 4 ^ 3 — неясно как будет вычислено это выражение: cначала 2 ^ 4 , а затем результат в степень 3 , или сначала 4 ^ 3 = 64 , а затем 2 ^ 64 ? Поэтому, в данном случае, необходимо использовать скобки: (2 ^ 4) ^ 3 или 2 ^ (4 ^ 3) — смотря что нужно.
Также распространенной ошибкой является запись вида: x ^ 3 / 4 — непонятно: вы хотите возвести x в куб и полученное выражение разделить на 4 , или хотите возвести x в степень 3 / 4 ? В последнем случае необходимо использовать скобки: x ^ (3 / 4) .

Ввод функций:

Функции вводятся с использованием маленьких латинских букв: sin ; cos ; tan ; log .
ВНИМАНИЕ! Аргумент функции всегда берется в скобки () , например: sin( 4 ) ; cos( x ) ; log( 4 + y ) .
Запись типа: sin 4 ; cos x ; log 4 + y — недопустима . Правильная запись: sin( 4 ) ; cos( x ) ; log( 4 + y ) .
Если необходимо возвести функцию в степень, например: синус x и все это в квадрате, это записывается вот так: (sin( x )) ^ 2 . Если необходимо возвести в квадрат аргумент, а не функцию (т.е синус от x ^ 2 ), тогда это выглядит вот так: sin( x ^ 2) . Запись типа: sin ^ 2 x — недопустима .

Читайте также:  Где хранятся расширения яндекс браузера

Вычисление логарифмов довольно распространённая операция в цифровой обработке сигналов. Чаще пожалуй приходится считать только свёртки (умножение с накоплением) и амплитуды с фазами. Как правило для вычисления логарифмов на FPGA применяется алгоритм CORDIC в гиперболическом варианте, требующий только таблицы и простых арифметических операций. Однако это не всегда бывает удобно, особенно если проект большой, кристалл маленький и начинаются танцы с оптимизацией. Именно с такой ситуацией и пришлось мне однажды столкнуться. Оба порта блока RAM (Cyclone IV) уже плотненько были в работе, не оставляя свободных окон. Использовать ещё один блок под гиперболический CORDIC не хотелось. Зато был умножитель, для которого во временной диаграмме получалось приличное свободное окно. Денёк подумав, я сочинил следующий алгоритм, в котором не используется таблиц, но есть умножение, точнее возведение в квадрат. И поскольку схемотехнически возведение в квадрат проще общего случая умножения, возможно этот алгоритм представляет интерес для специализированных микросхем, хотя для FPGA разницы конечно нет. Подробнее под катом.

Объяснять что к чему, тут проще для действительных чисел. С них и начнём. К целочисленной реализации перейдём потом.

Пусть есть число X. Требуется найти число Y такое, чтобы .
Положим так же что X лежит в интервале от 1 до 2. Это не слишком ограничивает общность, поскольку X всегда можно перевести в этот интервал умножением или делением на степень двойки. Для Y это будет означать добавление или вычитание целого числа, что делается легко. Итак X лежит в интервале от 1 до 2. Тогда Y будет лежать в интервале от 0 до 1. Запишем Y как бесконечную двоичную дробь:

Коэффициенты в этой записи есть ни что иное, как просто биты двоичного представления числа Y. Причём поскольку Y меньше 1, очевидно что =0.

Читайте также:  Взлом пароля на компе

Возведём наше первое уравнение в квадрат: и как и ранее, запишем двоичное представление числа 2Y. Очевидно, что

Т.е. биты остались теми же, просто сдвинулись степени двойки. Бита в представлении нет, потому что он равен нулю.

Возможны два случая:

1) 2$" data-tex="inline"> , 2Y > 1,

2) , 2Y

В первом случае в качестве нового значения X примем , во втором — .

В итоге задача свелась к прежней. Новое X опять лежит в интервале от 1 до 2, новое Y от 0 до 1. Но мы узнали один бит результата. Делая такие же шаги в дальнейшем, мы можем получить сколько угодно битов Y.

Посмотрим как это работает в программе на С:

Мы посчитали логарифм с точностью до 16 бит и сравнили с тем, что даёт математическая библиотека. Программа вывела:

res=0.485413, log=0.485427, err=0.002931%

Результат совпал с библиотекой с точностью 0.003%, что показывает работоспособность нашего алгоритма.

Перейдём к целочисленной реализации.

Пусть N-разрядные двоичные беззнаковые числа, отображают интервал [0, 1]. Для удобства будем считать единицей число , а не , и соответственно двойкой число . Напишем программу по образу и подобию предыдущей, но работающую с целыми числами:

Поиграв в программе с разными разрядностью чисел (DIG), точностью вычислений (N_BITS), и аргументами логарифма (w), видим, что всё вычисляется правильно. В частности с теми параметрами, которые заданны в этом исходнике, программа выдаёт:

val=0×27819, res=0x9BA5, log=0x9BA6, err=1

Теперь всё готово для того, чтобы реализовать на верилоге железку, делающую точно то же самое, что и функция myLog на С. Переменные s и u в нашей функции можно распечатать в цикле и сравнивать с тем, что выдает симулятор верилога. Соответствие этих переменных железной реализации весьма прозрачно и понятно. u это рабочий регистр, принимающий во время итераций новые значения X. s это сдвиговый регистр, в котором накапливается результат. Интерфейс нашего модуля будет выглядеть вот так:

Входная шина принята 18-разрядной, соответственно разрядности умножителей в Cyclone IV. Числа на наш модуль должны поступать нормализованные. Т.е. со старшим битом, равным единице. В моём проекте это выполнялось автоматически. Но в случае чего реализовать нормализатор, думаю никому труда не составит. Точность вычислений задаётся параметром nbits, по умолчанию равным 16. Модуль считает по одному биту за такт, и за 16 тактов вычислит логарифм с точностью до 16 битов. Если надо быстрее с той же точностью или точнее с той же скоростью, надеюсь никому не составит особого труда разделить модуль на несколько устройств и конвейеризовать.

Читайте также:  Как войти в автозапуск программ windows 7

Запустим тест вот таким скриптом:

Запустив тест, видим окончательный вывод симулятора — value=27819, result=9ba5. Верилог выдал то же самое что С. Временная диаграмма тут довольно тривиальна и особого интереса не представляет. Поэтому её не привожу.

Убеждаемся, что они совпадают бит в бит. Итого, реализация на верилоге повторяет с точностью до бита модель на С. Это и есть тот результат, которого следует достигать, реализуя алгоритмы в железе.

На этом пожалуй всё. Надеюсь кому-то этот мой опыт окажется полезен.

All | _ | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z

log2, log2f, log2l — расчет логарифма по основанию два

double log2 (double x);
float log2f (float x);
long double log2l (long double x);

x — число, логарифм которого требуется рассчитать.

Логарифм по основанию два от числа x.

Если, число х=0, то возвращается минус бесконечность (-inf), а переменной errno присваивается код ошибки ERANGE.

Если число x отрицательное, то возвращается признак nan, а переменной errno присваивается код ошибки EDOM.

Функции рассчитывают логарифм по основанию два от числа x.

Причем в функции log2f аргумент для расчета и возвращаемое значение задаются числами с плавающей точкой (тип float, точность не менее шести значащих десятичных цифр, разрядность — 32).

В функции log2 аргумент и возвращаемое значение задаются числами с плавающей точкой двойной точности (тип double, точность не менее десяти значащих десятичных цифр, разрядность — 64).

В функции log2l аргумент и возвращаемое значение задаются числами с плавающей точкой повышенной точности (тип long double, точность не менее десяти значащих десятичных цифр, разрядность — 80).

В примере рассчитывается натуральный логарифм от 3.11 с помощью функций log2f, log2 и log2l. Результаты работы функций log2f, log2 и log2l различаются точностью.

Аргумент: 3.11
log2f : 1.63691449165344238281
log2 : 1.63691458035587777964
log2l : 1.63691458035587778777