Big integer algorithm [04] bit operation, integer algorithm 04 operation

Source: Internet
Author: User

Big integer algorithm [04] bit operation, integer algorithm 04 operation

The previous article introduced the comparison of big integers. Today we will talk about bit-related operations.

 

Introduction

This article describes how big integers are represented by big integers. In order to facilitate the subsequent explanation, we first give an example of a large integer according to the previous definition (in a 32-bit system, each digit is 32 bits in length ):

Assume that there is a bignum x, the decimal value is 1134924633606254832, and the corresponding hexadecimal value is 0xfc00ff0f0f0f0. Then, according to the big integer representation, 2 ^ 32 is expressed as (each digit is separated by a comma ):

(262135232,4042322160) that is: 1134924633606254832/(2 ^ 32) = 264245232,113 109633606254832 mod (2 ^ 32) = 4042322160.

0000 1111 1100 0000 0000 1111 1111 0000

In binary format: 1111 0000 1111 0000 1111 0000 1111 0000

 

Returns the bits of the specified subscript pos.

The subscript (pos) starts from the lowest of the big integer and uses 0 as the starting value. For example, the bits marked as 3 in bignum x are 0, the bitwise of subscript 4 is 1.

For a given pos value, to find out where the corresponding bit is, you can first find the number of BITs corresponding to the pos in the big integer. For example, if pos is 38, pos/biL = 38/32 = 1,

BiL (bits in limbs) is the bit length of a number, and the biL is 32 in a 32-bit system. In this way, we can know that the bits corresponding to the pos are in the second digit of the big integer x (corresponding to the array unit with the subscript of 1 ). After finding the approximate position, you must determine the specific position in the digit. This can be obtained through the remainder operation: pos % biL = 38 mod 32 = 6, in this way, after shifting the digit to the right six digits and then performing a logic and operation with the digit 1, the bit value corresponding to the pos is 1 (corresponding to the digit marked in red ). (0000 1111 1100 0000 0000 1111 1111 0000 1111 billion, 1111 0000 1111 0000 1111 0000)

boolean bn_get_bit(const bignum *x, const size_t pos)
{
    boolean bit;

    //pos is zero base number

    if(x->alloc * biL <= pos)
        return 0;

    bit = (x->dp[pos / biL] >> (pos & (biL - 1))) & 1;

    return bit;
}

In the complement operation of 2, the calculation of a mod (2 ^ n) is equivalent to a AND (2 ^ n-1 ).

 

Set bits in the corresponding position for the pos.

As with the previous principle, first find the position of the bits corresponding to the pos. If pos = 35, offset = pos/biL = 1, mod = pos/biL = 3. After finding the corresponding position, you must first clear the value of this bit. The specific practice is to shift 1 to the left mod = 3 places, and then take the inverse, in this case, the binary value of the operation result is 1111 1111 1111 1111 1111 1111 1111. The binary value is calculated with the second digit of the large integer (corresponding to the array subscript of 1, then, the value of this bit is cleared. Then, the new bit can be set after the value of the boolean type is shifted to three places by mod = and then the second digit of the big integer is used for the OR operation.

int bn_set_bit (bignum * x, const size_t pos, boolean value)
{
     int ret = 0;
     size_t offset, mod;

     // pos is zero base number

     if (value! = TRUE && value! = FALSE)
         return BN_INVALID_INPUT;

     offset = pos / biL;
     mod = pos & (biL-1);

     if (pos> = x-> alloc * biL)
     {
         if (value == FALSE) return 0; // If pos exceeds the allocated digits and value is 0, no operation is needed, because the high-order bits default to 0, otherwise you need to increase the precision.
         BN_CHECK (bn_grow (x, offset + 1));
     }

     x-> dp [offset] & = ~ ((bn_digit) 1 << mod);
     x-> dp [offset] | = ((bn_digit) (value) << mod);

     x-> used = x-> alloc; // If the precision of bignum increases, you need to check the significant digits from the leftmost digit to the right to ensure that the used value is correct.
     bn_clamp (x); // compress extra bits

clean:

     return ret;
}

 

★Returns the number of valid bits.

Valid bits refer to all the bits starting from the first bit not 0 to the rightmost bit from the left. For example, in the example given in this article, except the first four bits of the highest bits, all other bits are valid bits, and the number of valid bits is 60. As mentioned above, you can easily obtain the following algorithm:

size_t bn_msb(const bignum *x)
{
    size_t i, j;

    i = x->used - 1;

    for(j = biL; j > 0; j--)
        if(((x->dp[i] >> (j - 1)) & 1) != 0)
            break;

    return biL * i + j;
}

The significance of this algorithm is that it can calculate the actual bit size of a bignum. Although it is simple, it will be used multiple times in many of the following algorithms.

 

★Returns the number of the first 0 valid bits.

The lowest valid bit is the first bit not 0 from the right, in this example, the minimum valid bits of bignum x are the bits whose subscript is 4 from the right in the lower digit. The number of preceding 0 values is 4. Therefore, the following algorithms can be easily written:

size_t bn_lsb(const bignum *x)
{
    size_t i, j;

    for(i = 0; i < x->used; i++)
    {
        if(x->dp[i] != 0)
        {
            for(j = 0; j < biL; j++)
            {
                if(((x->dp[i] >> j) & 1) != 0)
                    return i * biL + j;
            }
        }
    }

    return 0;
}

An integer p (p> 0) can be expressed in the following form: p = q * 2 ^ r, where q is an odd number, for example, 36 = 9*2 ^ 2, r = 2. The bn_lsb algorithm is used to calculate the r value by calculating the number of the first 0 valid bits. Although this algorithm is also very simple, it will show its skills in the algorithm that calculates the maximum common number.

 

★Returns the byte size of bignum.

Note that this operation does not return the memory occupied by bignum. For example, if bignum x is allocated with three units of memory at the beginning, its byte size is still 8 bytes. To calculate the byte size of bignum, you only need to add the bit size of x to 7 divided by 8. The purpose of 7 is to avoid the loss of one byte after the division of the bitwise of x is not a multiple of 8.

size_t bn_size(const bignum *x)
{
    return ((bn_msb(x) + 7) >> 3);
}

★Summary

It is not difficult to define the operation principle of the entire number, but if the bignum structure is not defined at the beginning, for example, using decimal, the operation is quite troublesome, this once again demonstrates that binary thinking is very important in programming. The next article will introduce the big integer shift operation.

 

[Back to the directory of this series]

 

Copyright Notice
Original blog, reproduced must contain this statement, to maintain the integrity of this article, and in the form of hyperlink to indicate the author Starrybird and the original address of this article: http://www.cnblogs.com/starrybird/p/4355521.html


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.