Как я могу добавить и вычесть целые числа на 128 битов в C или C++, если мой компилятор не поддерживает их?

Я бы удалил все классы .active, если вы нажмете на ссылку меню и установите класс .active для нажатой ссылки.

const links = document.querySelectorAll('.links > a');

const changeActive = (e) => {
  [...links].forEach(link => link.classList.remove('active'));
  e.target.classList.add('active');
}

[...links].forEach(e => e.addEventListener('click', changeActive));
.active {
  font-weight: bold;
}
<div class="navbar">
  <a href="#" class="toggle" id="nav-hamburger">
    <i class="fas fa-bars"></i>
    <a href="#" class="brand">Appeal Digital</a>
  </a>
  <div class="links">
    <a href="#" class="link active">Home</a>
    <a href="#" class="link">Who are we?</a>
    <a href="#" class="link">Meet the Team</a>
    <a href="#" class="link">Contact Us</a>
  </div>
</div>

23
задан Ciro Santilli 新疆改造中心法轮功六四事件 27 October 2015 в 04:49
поделиться

5 ответов

Если вам нужно только добавить и вычитание, и у вас уже есть ваши 128-битные значения в двоичной форме, библиотека может быть удобной, но не является строго обязательной. Эту математику тривиально сделать самостоятельно.

Я не знаю, что ваш компилятор использует для 64-битных типов, поэтому я ' Я буду использовать INT64 и UINT64 для 64-разрядных целых чисел со знаком и без знака.

class Int128
{
public:
    ...
    Int128 operator+(const Int128 & rhs)
    {
        Int128 sum;
        sum.high = high + rhs.high;
        sum.low = low + rhs.low;
        // check for overflow of low 64 bits, add carry to high
        if (sum.low < low)
            ++sum.high;
        return sum;
    }
    Int128 operator-(const Int128 & rhs)
    {
        Int128 difference;
        difference.high = high - rhs.high;
        difference.low = low - rhs.low;
        // check for underflow of low 64 bits, subtract carry to high
        if (difference.low > low)
            --difference.high;
        return difference;
    }

private:
    INT64  high;
    UINT64 low;
};
38
ответ дан 29 November 2019 в 00:51
поделиться

Существует много литературы относительно больших целых чисел. Вы можете использовать одну из свободно доступных библиотек (см. Ссылки) или вы можете свернуть свою собственную. Хотя я должен предупредить вас, что для чего-то более сложного, чем сложение и вычитание (и сдвиги), вам нужно использовать нетривиальные алгоритмы.

Чтобы сложить и вычесть, вы можете создать класс / структуру, которая содержит два 64- битовые целые числа. Вы можете использовать простую школьную математику для сложения и вычитания. По сути, делайте то, что вы делаете, с помощью карандаша и бумаги, чтобы сложить или вычесть, с внимательным вниманием к заимствованиям / заимствованиям.

Найдите большое целое число. Кстати, последние версии компиляторов VC ++, IntelC ++ и GCC имеют 128-битные целочисленные типы, хотя я не уверен, что они так легко доступны, как вы могли бы (они предназначены для использования с регистрами sse2 / xmms). [Один тысяча двести сорок семь] http://en.wikipedia.org/wiki/Arbitrary_precision_arithmetic

  • http://orion.math.iastate.edu/cbergman/crypto/bignums.html
  • http://www.mathgoodies.com / tutorial /
  • 3
    ответ дан 29 November 2019 в 00:51
    поделиться

    TomsFastMath немного похож на GMP (упомянутый выше), но является общественным достоянием и был разработан с очень быстро (даже содержит оптимизацию кода сборки для x86, x86-64, ARM, SSE2, PPC32 и AVR32).

    2
    ответ дан 29 November 2019 в 00:51
    поделиться

    Взгляните на GMP .

    #include <stdio.h>
    #include <gmp.h>
    
    int main (int argc, char** argv) {
        mpz_t x, y, z;
        char *xs, *ys, *zs;
        int i;
        int base[4] = {2, 8, 10, 16};
    
        /* setting the value of x in base 10 */
        mpz_init_set_str(x, "100000000000000000000000000000000", 10);
    
        /* setting the value of y in base 16 */
        mpz_init_set_str(y, "FF", 16);
    
        /* just initalizing the result variable */
        mpz_init(z);
    
        mpz_sub(z, x, y);
    
        for (i = 0; i < 4; i++) {
            xs = mpz_get_str(NULL, base[i], x);
            ys = mpz_get_str(NULL, base[i], y);
            zs = mpz_get_str(NULL, base[i], z);
    
            /* print all three in base 10 */
            printf("x = %s\ny = %s\nz = %s\n\n", xs, ys, zs);
    
            free(xs);
            free(ys);
            free(zs);
        }
    
        return 0;
    }
    

    Вывод

    x = 10011101110001011010110110101000001010110111000010110101100111011111000000100000000000000000000000000000000
    y = 11111111
    z = 10011101110001011010110110101000001010110111000010110101100111011111000000011111111111111111111111100000001
    
    x = 235613266501267026547370040000000000
    y = 377
    z = 235613266501267026547370037777777401
    
    x = 100000000000000000000000000000000
    y = 255
    z = 99999999999999999999999999999745
    
    x = 4ee2d6d415b85acef8100000000
    y = ff
    z = 4ee2d6d415b85acef80ffffff01
    
    16
    ответ дан 29 November 2019 в 00:51
    поделиться

    Наткнувшись на этот относительно старый пост совершенно случайно, я подумал, что уместно развить предыдущую гипотезу Вольта для неопытных читателей.

    Во-первых, диапазон со знаком 128-битного числа составляет от -2 127 до 2 127 -1, а не от -2 127 до 2 127 , как было предусмотрено изначально.

    Во-вторых, из-за циклического характера конечной арифметики наибольшая требуемая разница между двумя 128-битными числами составляет от -2 127 до 2 127 -1, что требует наличия необходимого хранилища. 128 бит, а не 129. Хотя (2 127 -1) - (-2 127 ) = 2 128 -1, что явно больше, чем у нашего максимум 2 127 -1 положительное целое число, арифметическое переполнение всегда гарантирует, что ближайшее расстояние между любыми двумя n -битными числами всегда попадает в диапазон от 0 до 2 n -1 и, следовательно, неявно от -2 n -1 до 2 n -1 -1.

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

    0 = 000b
    1 = 001b
    2 = 010b
    3 = 011b
    4 = 100b
    5 = 101b
    6 = 110b
    7 = 111b ---> [Возврат к 000b при переполнении]

    Из приведенной выше таблицы ясно видно, что:

    001b (1) + 010b (2) = 011b (3)

    Это также очевидно, что сложение любого из этих чисел с его числовым дополнением всегда дает 2 n -1:

    010b (2) + 101b ([дополнение 2] = 5) = 111b (7) = ( 2 3 -1)

    Из-за циклического переполнения, которое происходит, когда сложение двух n -битных чисел приводит к ( n +1) -битовый результат, из этого следует, что добавление любого из этих чисел с его числовым дополнением + 1 всегда будет давать 0:

    010b (2) + 110b ([дополнение 2] + 1) = 000b (0)

    Таким образом, мы можем сказать, что [дополнение к n ] + 1 = - n , так что n + [дополнение к n ] + 1 = n + (- n ) = 0. Кроме того, если мы теперь знаем, что n + [дополнение к n ] + 1 = 0, тогда n + [компл. элемент n - x ] + 1 должен = n - ( n - x ) = х .

    Применяя это к нашей исходной 3-битной таблице, получаем:

    0 = 000b = [дополнение 0] + 1 = 0
    1 = 001b = [дополнение из 7] + 1 = -7
    2 = 010b = [дополнение из 6] + 1 = -6
    3 = 011b = [дополнение из 5] + 1 = -5
    4 = 100b = [дополнение из 4] + 1 = -4
    5 = 101b = [дополнение из 3] + 1 = -3
    6 = 110b = [дополнение 2] + 1 = -2
    7 = 111b = [дополнение 1] + 1 = -1 ---> [Циклический возврат к 000b при переполнении]

    Является ли репрезентативная абстракция положительной, отрицательной или комбинацией обоих, как подразумевается с арифметикой со знаком с дополнением до двух. , теперь у нас есть 2 n n -битных паттернов, которые могут беспрепятственно обслуживать как положительные значения от 0 до 2 n -1, так и отрицательные 0 до - (2 n ) - 1 диапазон по мере необходимости. Фактически, все современные процессоры используют именно такую ​​систему для реализации общей схемы ALU как для операций сложения, так и для операций вычитания. Когда ЦП встречает инструкцию вычитания i1 - i2 ,он внутренне выполняет операцию [дополнение + 1] на i2 и затем обрабатывает операнды через схему сложения, чтобы вычислить i1 + [дополнение i2 ] + 1. За исключением дополнительного флага переноса / знака, управляемого XOR-gated, сложение как со знаком, так и без знака, а также косвенное вычитание являются неявными.

    Если мы применим приведенную выше таблицу к входной последовательности [-2 n -1 , 2 n -1 -1, -2 n -1 ], как представлено в исходном ответе Вольта, теперь мы можем вычислить следующие n-битные разности:

    diff # 1:
    (2 n -1 -1) - (-2 n -1 ) =
    3 - (-4) = 3 + 4 =
    (-1) = 7 = 111b

    разница №2:
    (-2 n -1 ) - (2 n -1 -1) =
    (-4) - 3 = (-4) + (5) =
    (-7) = 1 = 001b

    Начиная с нашего начального числа -2 n -1 , теперь мы можем воспроизвести исходную входную последовательность, последовательно применяя каждый из вышеуказанных дифференциалов:

    (-2 n -1 ) + (разница № 1) =
    (-4) + 7 = 3 =
    2 n -1 -1

    (2 n -1 -1) + (разница № 2) =
    3 + (-7) = (-4) =
    -2 n -1

    Вы, конечно, можете захотеть принять более философский подход к этой проблеме и предположить, почему 2 n циклически последовательных чисел потребуют более 2 п циклически-последовательные дифференциалы?

    Талиадон.

    8
    ответ дан 29 November 2019 в 00:51
    поделиться
    Другие вопросы по тегам:

    Похожие вопросы: