Jump to content

Алгоритм БКМ

Алгоритм BKM — это алгоритм сложения и сложения для вычисления элементарных функций , впервые опубликованный в 1994 году Жан-Клодом Бажаром, Сильванусом Кла и Жаном-Мишелем Мюллером. BKM основан на вычислении комплексных логарифмов ( L-режим ) и экспонент ( E-режим ) с использованием метода, аналогичного алгоритму, который Генри Бриггс использовал для вычисления логарифмов. Используя предварительно вычисленную таблицу логарифмов отрицательных степеней двойки, алгоритм BKM вычисляет элементарные функции, используя только операции сложения, сдвига и сравнения целых чисел.

BKM похож на CORDIC , но использует таблицу логарифмов, а не таблицу арктангенсов . На каждой итерации выбор коэффициента производится из набора из девяти комплексных чисел: 1, 0, −1, i, −i, 1+i, 1−i, −1+i, −1−i, а не только -1 или +1, как используется CORDIC. BKM предоставляет более простой метод вычисления некоторых элементарных функций, и в отличие от CORDIC, BKM не требует коэффициента масштабирования результата. Скорость сходимости BKM составляет примерно один бит на итерацию, как и CORDIC, но BKM требует большего количества предварительно вычисленных элементов таблицы для той же точности, поскольку таблица хранит логарифмы комплексных операндов.

Как и другие алгоритмы класса сложения и сложения, BKM особенно хорошо подходит для аппаратной реализации. Относительная производительность программной реализации BKM по сравнению с другими методами, такими как полиномиальные или рациональные аппроксимации, будет зависеть от наличия быстрых многобитовых сдвигов (т.е. бочкового сдвига ) или аппаратной арифметики с плавающей запятой .

Чтобы решить уравнение

алгоритм BKM использует основное свойство логарифмов

Используя обозначение Пи , это тождество обобщается до

Поскольку любое число может быть представлено произведением, это позволяет нам выбирать любой набор значений. которые умножаются, чтобы получить значение, с которого мы начали. В компьютерных системах умножать и делить на кратные 2 гораздо быстрее, но поскольку не каждое число кратно 2, используя это лучший вариант, чем более простой выбор . Поскольку мы хотим начать с больших изменений и добиться более точных результатов, увеличивается, мы можем более конкретно использовать , что позволяет продукту приближаться к любому значению от 1 до ~4,768, в зависимости от того, какое подмножество мы используем в конечном продукте. На данный момент приведенное выше уравнение выглядит следующим образом:

Этот выбор снижает вычислительную сложность произведения от многократного умножения до простого сложения и сдвига битов в зависимости от реализации. Наконец, сохраняя значения в таблице вычисление решения также является простым сложением. Итеративно это дает нам две отдельные последовательности. Одна последовательность приближается к входному значению в то время как другой приближается к выходному значению :

Учитывая это рекурсивное определение и поскольку строго возрастает, то с помощью индукции и сходимости можно показать , что

для любого . Для расчета вывода мы сначала создаем справочную таблицу

Затем выходные данные вычисляются итеративно по определению Условия в этой итерации такие же, как и условия для ввода. Как и входные данные, эта последовательность также строго возрастает, поэтому можно показать, что

для любого .

Поскольку приведенный выше алгоритм вычисляет и входные, и выходные данные одновременно, его можно немного изменить, чтобы известное значение и — это значение, которое мы хотим вычислить, тем самым вычисляя экспоненту вместо логарифма. Поскольку в этом случае x становится неизвестным, условие меняется с

к

Функция логарифма

[ редактировать ]

Чтобы вычислить функцию логарифма (L-режим), алгоритм на каждой итерации проверяет, если . Если да, то он вычисляет и . После итераций значение функции известно с погрешностью .

Пример программы для вычисления натурального логарифма на C++ (см. A_e для стола):

 double log_e (const double Argument, const int Bits = 53) // 1 <= Argument <= 4.768462058
 {
    double  x = 1.0, y = 0.0, s = 1.0;

    for (int k = 0; k < Bits; k++) {
      double const  z = x + x*s;
      if (z <= Argument) {
          x  = z;
          y += A_e[k];
      }
      s *= 0.5;
    }
    return y;
 }

Логарифмы для оснований, отличных от e, можно вычислить с аналогичными усилиями.

Пример программы для вычисления двоичного логарифма на C++ (см. A_2 для стола):

 double log_2 (const double Argument, const int Bits = 53) // 1 <= Argument <= 4.768462058
 {
    double  x = 1.0, y = 0.0, s = 1.0;

    for (int k = 0; k < Bits; k++) {
      double const  z = x + x*s;
      if (z <= Argument) {
          x  = z;
          y += A_2[k];
      }
      s *= 0.5;
    }
    return y;
 }

Допустимый диапазон аргументов одинаков для обоих примеров (1 ≤ Argument ≤ 4,768462058…). В случае логарифма по основанию 2 показатель степени можно разделить заранее (чтобы получить целую часть), чтобы алгоритм можно было применить к остатку (между 1 и 2). Поскольку аргумент меньше 2,384231…, итерация k может начинаться с 1. Работая в любой системе счисления, умножение на s можно заменить прямым изменением показателя степени с плавающей запятой, вычитая из него 1 во время каждой итерации. В результате алгоритм использует только сложение, а не умножение.

Экспоненциальная функция

[ редактировать ]

Чтобы вычислить экспоненциальную функцию (режим E), алгоритм на каждой итерации проверяет, если . Если да, то он вычисляет и . После итераций значение функции известно с погрешностью .

Пример программы на C++ (см. A_e для стола):

 double exp (const double Argument, const int Bits = 54)	// 0 <= Argument <= 1.5620238332
 {
   double  x = 1.0, y = 0.0, s = 1.0;

   for (int k = 0; k < Bits; k++) {
      double const  z = y + A_e[k];
      if (z <= Argument) {
         y = z;
         x = x + x*s;
      }
      s *= 0.5;
   }
   return x;
 }

Таблицы для примеров

[ редактировать ]
static const double A_e [] = ...
 static const double A_e [] = // A_e[k] = ln (1 + 0.5^k)
 {
   0.693147180559945297099404706000, 0.405465108108164392935428259000,
   0.223143551314209769962616701000, 0.117783035656383447138088388000,
   0.060624621816434840186291518000, 0.030771658666753686222134530000,
   0.015504186535965253358272343000, 0.007782140442054949100825041000,
   0.003898640415657322636221046000, 0.001951220131261749216850870000,
   0.000976085973055458892686544000, 0.000488162079501351186957460000,
   0.000244110827527362687853374000, 0.000122062862525677363338881000,
   0.000061033293680638525913091000, 0.000030517112473186377476993000,
   0.000015258672648362398138404000, 0.000007629365427567572417821000,
   0.000003814689989685889381171000, 0.000001907346813825409407938000,
   0.000000953673861659188260005000, 0.000000476837044516323000000000,
   0.000000238418550679858000000000, 0.000000119209282445354000000000,
   0.000000059604642999033900000000, 0.000000029802321943606100000000,
   0.000000014901161082825400000000, 0.000000007450580569168250000000,
   0.000000003725290291523020000000, 0.000000001862645147496230000000,
   0.000000000931322574181798000000, 0.000000000465661287199319000000,
   0.000000000232830643626765000000, 0.000000000116415321820159000000,
   0.000000000058207660911773300000, 0.000000000029103830456310200000,
   0.000000000014551915228261000000, 0.000000000007275957614156960000,
   0.000000000003637978807085100000, 0.000000000001818989403544200000,
   0.000000000000909494701772515000, 0.000000000000454747350886361000,
   0.000000000000227373675443206000, 0.000000000000113686837721610000,
   0.000000000000056843418860806400, 0.000000000000028421709430403600,
   0.000000000000014210854715201900, 0.000000000000007105427357600980,
   0.000000000000003552713678800490, 0.000000000000001776356839400250,
   0.000000000000000888178419700125, 0.000000000000000444089209850063,
   0.000000000000000222044604925031, 0.000000000000000111022302462516,
   0.000000000000000055511151231258, 0.000000000000000027755575615629,
   0.000000000000000013877787807815, 0.000000000000000006938893903907,
   0.000000000000000003469446951954, 0.000000000000000001734723475977,
   0.000000000000000000867361737988, 0.000000000000000000433680868994,
   0.000000000000000000216840434497, 0.000000000000000000108420217249,
   0.000000000000000000054210108624, 0.000000000000000000027105054312
 };
static const double A_2 [] = ...

Примечания

[ редактировать ]

Дальнейшее чтение

[ редактировать ]
Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: 7c5074658a4ec51a0978e6aa0a683060__1691297940
URL1:https://arc.ask3.ru/arc/aa/7c/60/7c5074658a4ec51a0978e6aa0a683060.html
Заголовок, (Title) документа по адресу, URL1:
BKM algorithm - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)