Oc-windows.ru

IT Новости из мира ПК
20 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Java логарифм по основанию 2

Java логарифм по основанию 2

я использую следующую функцию для вычисления журнала базы 2 числа:

есть Ли у нее оптимальной производительности?

кто-нибудь знает готов J2SE API-функции для этой цели?

UPD1 Удивительно для меня, float point арифметика, кажется, быстрее, чем целочисленной арифметики.

UPD2 из-за комментариев, которые мне будут проводить более детальное расследование.

Я использую следующую функцию для вычисления базы журнала 2 для целых чисел:

имеет ли он оптимальную производительность?

кто-нибудь знает готовую функцию API J2SE для этой цели?

UPD1 удивительно для меня, арифметика с плавающей запятой кажется быстрее, чем целочисленная арифметика.

UPD2 из-за комментариев я проведу более подробную расследование.

UPD3 моя целочисленная арифметическая функция в 10 раз быстрее, чем математика.log (n)/математика.log (2).

9 ответов

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

Я обычно стараюсь избегать вычислений FP, когда это возможно.

операции с плавающей запятой не являются точными. Вы никогда не можете знать наверняка, что будет (int)(Math.log(65536)/Math.log(2)) оценить. Например, Math.ceil(Math.log(1 30 на моем ПК, где математически это должно быть ровно 29. Я не нашел значения для x, где (int)(Math.log(x)/Math.log(2)) не удается (только потому, что есть только 32 «опасных» значения), но это не означает, что он будет работать одинаково на любом ПК.

обычный трюк здесь-использование «Эпсилона» при округлении. Как (int)(Math.log(x)/Math.log(2)+1e-10) никогда не должно терпеть неудачу. Выбор этого «Эпсилона» не является тривиальной задачей.

больше демонстрации, используя более общую задачу-попытка реализовать int log(int x, int base) :

если мы используем самую прямую реализацию логарифма,

чтобы полностью избавиться от ошибок, мне пришлось добавить epsilon, который находится между 1e-11 и 1e-14. Могли бы вы сказать это до тестирования? Я определенно не мог.

это функция, которую я использую для такого расчета:

это немного быстрее, чем Integer.numberOfLeadingZeros () (20-30%) и почти в 10 раз быстрее (jdk 1.6 x64), чем математика.реализация на основе log (), подобная этой:

обе функции возвращают одинаковые результаты для всех возможных входных значений.

обновление: Java 1.7 server JIT способен заменить несколько статических математических функций альтернативными реализациями на основе встроенных процессоров. Одна из этих функций-Integer.numberOfLeadingZeros (). Таким образом, с 1.7 или более новой серверной виртуальной машиной реализация, подобная той, о которой идет речь, на самом деле немного быстрее, чем binlog выше. К сожалению, клиент JIT, похоже, не имеет этой оптимизации.

эта реализация также возвращает те же результаты для всех 2^32 возможных входных значений, что и две другие реализации, опубликованные выше.

вот фактическое время выполнения на мой компьютер (Sandy Bridge i7):

Вы здесь: Главная >> Java-самоучитель >> Математический объект Math

Обучающие курсы:

Математический объект Math

Рассмотрим математический объект — Math. Основные свойства и методы этого объекта представлены в табл. 11.11.

Таблица 11.11. Основные методы объекта Math

Натуральный логарифм числа 2

Натуральный логарифм числа 10

Логарифм по основанию 2 числа е

Логарифм по основанию 10 числа е

Квадратный корень из 0,5

Квадратный корень из 2

Арккосинус аргумента в радианах

Арксинус аргумента в радианах

Арктангенс аргумента в радианах

Арктангенс частного отделения аргументов в радианах

Получает целое число, равное параметру или больше него

Возводит экспоненту в значение параметра

Получает целое число, равное параметру или меньше него

Возвращает натуральный логарифм

Возвращает максимальное из 2-х значений

Возвращает минимальное из 2-х значений

Возводит первый аргумент в степень второго

Возвращает случайное число от 0 (включительно) до 1 (исключая его)

Округляет число до целого числа

Вычисляет квадратный корень

Приведем пример использования объекта Math (листинг 11.11).

Листинг 11.11. Пример использования объекта Math

Рассмотрим объект Number. Основные свойства и методы этого объекта представлены в табл. 11.12.

Таблица 11.12. Основные методы объекта Number

Максимальное значение числа в JavaScript

Минимальное значение числа в JavaScript

Специальное нечисловое значение

Преобразует в строку данные объекта

Возвращает строковое представление значения

Возвращает число как числовой тип данных

Наконец один из самых используемых объектов — string. Основные свойства и методы этого объекта представлены в табл. 11.13.

Таблица 11.13. Основные методы объекта Math

Приведем пример использования объекта String (листинг 11.12).

Листинг 11.12. Пример использования объекта String

Как это выглядит в окне браузера, показано на рис. 11.3.

Рис. 11.3. Результат выполнения листинга 11.12

В JavaScript есть еще множество объектов, например: Function, Global, RegЕхр и др. О них можно прочесть в специальной литературе.

Рассмотрение JavaScript мы на этом закончили. В следующей главе мы чуть подробнее познакомимся с языком гипертекстовой разметки HTML и посмотрим, каким образом можно связать HTML и JavaScript.

Резюме

1. В JavaScript нет классов, но есть структуры под названием объектные типы (называемые нами объектами). Можно создавать экземпляры объектов.

2. Можно создавать свои объекты с помощью функций, добавлять к ним дополнительные свойства.

3. Существует множество базовых объектов. Среди них есть объект, отвечающий за информацию о браузере (navigator), за HTML-документ и окно браузера (объект window с множеством его подобъектов).

Вопросы

1. Что такое объектный тип (объект)?
2. Что такое объект navigator?
3. Что такое объект document?
4. Что такое объект location?
5. Что такое объект history?
6. Что такое объект Math?
7. Что такое объект String?

Контрольные упражнения

1. Напишите текст HTML-документа, который использовал бы как можно больше объектов.
2. Создайте свой объект и HTML-документ, который бы его использовал.

Сергей Владимирцев
18.03.2011

Читать еще:  Inputstreamreader java пример

Логарифм

Логарифмическая функция является обратной к экспоненциальной функции. Логарифм по основанию b — это степень, до которой b необходимо возвести, чтобы получить заданное число. Например, равен степени, до которой 2 должно быть возведено, чтобы произвести 8. Ясно, что 2 ^ 3 = 8, так = 3. В общем случае при b> 0 и b не равно 1.

Факт о логарифме:

  1. Логарифмы были быстро приняты учеными из-за различных полезных свойств, которые упростили долгие, утомительные вычисления.
  2. Логарифм по основанию 10 (то есть b = 10) называется общим логарифмом и имеет много применений в науке и технике.
  3. Натуральный логарифм , является логарифмом с основанием е. Он используется в математике и физике из-за его более простой производной.
  4. Двоичный логарифм — это логарифм с основанием 2 и широко используется в информатике.

Законы логарифмов:

Как найти логарифм числа?

Наивное решение:
Идея состоит в том, чтобы создать функцию, которая вычисляет и возвращает , Например, если n = 64, то ваша функция должна вернуть 6, а если n = 129, то ваша функция должна вернуть 7.

// C программа для поиска log (n) с использованием рекурсии
#include

unsigned int Log2n(unsigned int n)

return (n > 1) ? 1 + Log2n(n / 2) : 0;

unsigned int n = 32;

printf ( «%u» , Log2n(n));

// Java-программа для поиска log (n)
// используя рекурсию

static int Log2n( int n)

return (n > 1 ) ? 1 + Log2n(n / 2 ) : 0 ;

public static void main(String args[])

# Python 3 программа для
# find log (n) с помощью рекурсии

return 1 + Log2n(n / 2 ) if (n > 1 ) else 0

// C # программа для поиска log (n)
// используя рекурсию

static int Log2n( int n)

return (n > 1) ? 1 + Log2n(n / 2) : 0;

public static void Main()

// PHP программа
// найти log (n) с помощью рекурсии

function Log2n( $n )

return ( $n > 1) ? 1 + Log2n( $n / 2) : 0;

Выход :

Временная сложность: O (log n)
Вспомогательное пространство: O (log n), если во время рекурсии учитывается размер стека, иначе O (1)

Эффективные решения:

Практикуйте задачи по логарифму:

Вопрос 1: Найти значение x в уравнении, заданном 8 x + 1 — 8 x-1 = 63
Решение: возьмите 8 х-1 общего из уравнения.
Это уменьшить до
8 х-1 (8 2 — 1) = 63
8 х-1 = 1
Следовательно, x — 1 = 0
х = 1

Вопрос 2: Найти значение х для уравнения. заданный лог 0,25 х = 16
Решение: журнал 0,25 х = 16
Можно написать как
х = (0,25) 16
х = (1/4) 16
х = 4 -16

Вопрос 3: Решите уравнение log 12 1728 x log 9 6561
Решение: это можно записать как
log 12 (12 3 ) x log 9 (9 4 )
= 3log 12 12 x 4log 9 9
= 3 х 4 = 12

Вопрос 4: Решите для х
log x 3 + log x 9 + log x 27 + log x 81 = 10

Решение: можно написать как
log x (3 x 9 x 27 x 81) = 10
log x (3 1 x 3 2 x 3 3 x 3 4 ) = 10
log x (3 10 ) = 10
10 log x 3 = 10
тогда х = 3

Вопрос 5: Если log (a + 3) + log (a — 3) = 1 , то a =?
Решение: log 10 ((a + 3) (a — 3)) = 1
log 10 (a 2 — 9) = 1
( 2 — 9) = 10
а 2 = 19
а = √19

Вопрос 6: Решите 1 / log ab (abcd) + 1 / log bc (abcd) + 1 / log cd (abcd) + 1 / log da (abcd)
Решение:
= log abcd (ab) + log abcd (bc) + log abcd (cd) + log abcd (da)
= log abcd (ab * bc * cd * da)
= log abcd (abcd) 2
= 2 log abcd (abcd)
= 2

Вопрос 7: Если xyz = 10, то решить log (x n y n / z n ) + log (y n z n / x n ) + log (z n x n / y n )
Решение:
log (x n y n / z n * y n z n / x n * z n x n / y n )
= log x n y n z n
= log (xyz) n
= log 10 10 n
= n

Вопрос 8: Найти (121/10) x = 3
Решение: нанесите логарифм с обеих сторон
журнал (121/10) (121/10) x = журнал (121/10) 3
x = (журнал 3) / (журнал 121 — журнал 10)
x = (log 3) / (2 log 11 — 1)

Вопрос 9: Решите log (2x 2 + 17) = log (x — 3) 2
Решение:
log (2x 2 + 17) = log (x 2 — 6x + 9)
2x 2 + 17 = x 2 — 6x + 9
х 2 + 6х + 8 = 0
х 2 + 4х + 2х + 8 = 0
х (х + 4) + 2 (х + 4) = 0
(х + 4) (х + 2) = 0
х = -4, -2

Вопрос 10: log 2 (33 — 3 x ) = 10 log (5 — x) . Решить для х.
Решение: положите х = 0
log 2 (33 — 1) = 10 log (5)
log 2 32 = 5
5 log 2 2 = 5
5 = 5
LHS = RHS

Больше проблем, связанных с логарифмом:

Класс Math

Класс Math содержит методы для выполнения основных числовых операций, таких как нахождение экспоненты, логарифма, квадратного корня и т. д.

Класс содержит две константы типа double: E и PI. Все методы в классе Math статичны.

LawsDescription
+
*
ТипМетодОписание
doubleabs(double a)Возвращает абсолютное значение (модуль) числа типа double.
floatabs(float a)Возвращает абсолютное значение (модуль) числа типа float .
intabs(int a)Возвращает абсолютное значение (модуль) числа типа int.
longabs(long a)Возвращает абсолютное значение (модуль) числа типа long.
doubleacos(double a)Возвращает арккосинус значения. Возвращенный угол находится в диапазоне от 0 до pi.
doubleasin(double a)Возвращает арксинус значения. Возвращенный угол в диапазоне от -pi/2 до pi/2.
doubleatan(double a)Возвращает арктангенс значения. Возвращенный угол в диапазоне от-pi/2 до pi/2.
doublecbrt(double a)Возвращает кубический корень аргумента.
doubleceil(double a)Возвращает наименьшее целое число, которое больше аргумента.
doublecopySign(double magnitude, double sign)Возвращает аргумент с тем же знаком, что у второго аргумента.
doublecopySign(float magnitude, float sign)Возвращает аргумент с тем же знаком, что у второго аргумента.
doublecos(double a)Возвращает косинус аргумента.
doublecosh(double x)Возвращает гиперболический косинус аргумента.
intdecrementExact(int a)Возвращает значение аргумента уменьшенное на единицу.
longdecrementExact(long a)Возвращает значение аргумента уменьшенное на единицу.
doubleexp(double a)Возвращает экспоненту аргумента.
doublefloor(double a)Возвращает наибольшее целое число, которое меньше или равно аргументу.
doublehypot(double x, double y)Возвращает длину гипотенузы (sqrt(x 2 +y 2 )).
doubleIEEEremainder(double f1, double f2)Возвращает остаток от деления f1 на f2.
intincrementExact(int a)Возвращает значение аргумента увеличенное на единицу.
longincrementExact(long a)Возвращает значение аргумента увеличенное на единицу.
doublelog(double a)Возвращает натуральный логарифм (по основанию e).
doublelog10(double a)Возвращает логарифм по основанию 10.
doublemax(double a, double b)Возвращает больший из аргументов.
floatmax(float a, float b)Возвращает больший из аргументов.
intmax(int a, int b)Возвращает больший из аргументов.
longmax(long a, long b)Возвращает больший из аргументов.
doublemin(double a, double b)Возвращает меньший из аргументов.
floatmin(float a, float b)Возвращает меньший из аргументов.
intmin(int a, int b)Возвращает меньший из аргументов.
longmin(long a, long b)Возвращает меньший из аргументов.
intmultiplyExact(int x, int y)Возвращает произведение аргументов (x*y).
longmultiplyExact(long x, long y)Возвращает произведение аргументов (x*y).
intnegateExact(int a)Возвращает отрицательное значение аргумента.
longnegateExact(long a)Возвращает отрицательное значение аргумента.
doublepow(double a, double b)Возвращает значение первого аргумента, возведенное в степень второго аргумента.
doublerandom()Возвращает случайное число от 0.0 (включительно) до 1 (не включительно).
doublerint(double a)Возвращает округленное значение аргумента.
intround(double a)Возвращает округленное значение аргумента.
doublesignum(double a)Возвращает знак аргумента.
floasignum(float a)Возвращает знак аргумента.
doublesin(double a)Возвращает синус аргумента.
doublesinh(double a)Возвращает гиперболический синус аргумента.
doublsqrt(double a)Возвращает квадратный корень аргумента.
intsubtractExact(int x, int y)Возвращает разность аргументов (x-y).
longsubtractExact(long x, long y)Возвращает разность аргументов (x-y).
doubletan(double a)Возвращает тангенс аргумента.
doubletanh(double a)Возвращает гиперболический тангенс аргумента.
doubltoDegrees()Преобразует радианы в градусы.
inttoIntExact(long value)Преобразует аргумент типа long в int.
doubltoRadians()Преобразует градусы в радианы.

abs(double a) — возвращает абсолютное значение (модуль) числа типа double.

abs(float a) — возвращает абсолютное значение (модуль) числа типа float .

abs(int a) — возвращает абсолютное значение (модуль) числа типа int.

abs(long a) — возвращает абсолютное значение (модуль) числа типа long.

acos(double a) — возвращает арккосинус значения. Возвращенный угол находится в диапазоне от 0 до pi.

asin(double a) — возвращает арксинус значения. Возвращенный угол в диапазоне от -pi/2 до pi/2.

atan(double a) — возвращает арктангенс значения. Возвращенный угол в диапазоне от-pi/2 до pi/2.

cbrt(double a) — возвращает кубический корень аргумента.

ceil(double a) — возвращает наименьшее целое число, которое больше аргумента.

copySign(double magnitude, double sign) — возвращает аргумент с тем же знаком, что у второго аргумента.

copySign(float magnitude, float sign) — возвращает аргумент с тем же знаком, что у второго аргумента.

cos(double a) — возвращает косинус аргумента.

cosh(double x) — возвращает гиперболический косинус аргумента.

decrementExact(int a) — возвращает значение аргумента уменьшенное на единицу.

decrementExact(long a) — возвращает значение аргумента уменьшенное на единицу.

exp(double a) — возвращает экспоненту аргумента.

floor(double a) — возвращает наибольшее целое число, которое меньше или равно аргументу.

hypot(double x, double y) — возвращает длину гипотенузы (sqrt(x 2 +y 2 )).

IEEEremainder(double f1, double f2) — возвращает остаток от деления f1 на f2.

incrementExact(int a) — возвращает значение аргумента увеличенное на единицу.

incrementExact(long a) — возвращает значение аргумента увеличенное на единицу.

log(double a) — возвращает натуральный логарифм (по основанию e).

log10(double a) — возвращает логарифм по основанию 10.

max(double a, double b) — возвращает больший из аргументов.

max(float a, float b) — возвращает больший из аргументов.

max(int a, int b) — возвращает больший из аргументов.

max(long a, long b) — возвращает больший из аргументов.

min(double a, double b) — возвращает меньший из аргументов.

min(float a, float b) — возвращает меньший из аргументов.

min(int a, int b) — возвращает меньший из аргументов.

min(long a, long b) — возвращает меньший из аргументов.

multiplyExact(int x, int y) — возвращает произведение аргументов (x*y).

multiplyExact(long x, long y) — возвращает произведение аргументов (x*y).

negateExact(int a) — возвращает отрицательное значение аргумента.

negateExact(long a) — возвращает отрицательное значение аргумента.

pow(double a, double b) — возвращает значение первого аргумента, возведенное в степень второго аргумента (a b )

random() — возвращает случайное число от 0.0 (включительно) до 1 (не включительно).

rint(double a) — возвращает округленное значение аргумента.

round(double a) — возвращает округленное значение аргумента.

signum(double a) — возвращает знак аргумента.

signum(float a) — возвращает знак аргумента.

sin(double a) — возвращает синус аргумента.

sinh(double a) — возвращает гиперболический синус аргумента.

sqrt(double a) — возвращает квадратный корень аргумента.

subtractExact(int x, int y) — возвращает разность аргументов (x-y).

subtractExact(long x, long y) — возвращает разность аргументов (x-y).

tan(double a) — возвращает тангенс аргумента.

tanh(double a) — возвращает гиперболический тангенс аргумента.

toDegrees() — преобразует радианы в градусы.

toIntExact(long value) — преобразует аргумент типа long в int.

toRadians() — преобразует градусы в радианы.

Один способ вычисления логарифма по основанию 2

Вычисление логарифмов довольно распространённая операция в цифровой обработке сигналов. Чаще пожалуй приходится считать только свёртки (умножение с накоплением) и амплитуды с фазами. Как правило для вычисления логарифмов на 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=0x27819, res=0x9BA5, log=0x9BA6, err=1

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

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

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

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

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

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

Ссылка на основную публикацию
Adblock
detector