微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何正确进行 GMP 位移?

如何解决如何正确进行 GMP 位移?

我需要使用大精度整数进行一些计算,并希望使用 GMP 库。我希望有人在这里有经验,因为我不明白如何使用位移。我正在尝试使用下面的代码代码编译但 b 仍然包含 0。

https://gmplib.org/manual/Low_002dlevel-Functions

#include <stdio.h>                                                                                                                                                                                                                           
#include <gmp.h>                                                                                                                                                                                                                             
                                                                                                                                                                                                                                             
int main()                                                                                                                                                                                                                                   
{                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                             
    mpz_t a;                                                                                                                                                                                                                                 
    mpz_t b;                                                                                                                                                                                                                                 
                                                                                                                                                                                                                                             
    mpz_init2(b,a->_mp_size);                                                                                                                                                                                                               
    mpz_set_str(a,"1",16);                                                                                                                                                                                                                 
                                                                                                                                                                                                                                             
    mp_limb_t bits = mpn_lshift(b->_mp_d,&a->_mp_d[0],a->_mp_size,1);                                                                                                                                                                     
                                                                                                                                                                                                                                             
    gmp_printf("%Zx\n",a);                                                                                                                                                                                                                  
    gmp_printf("Bits shifted %M\n",bits);                                                                                                                                                                                                   
    gmp_printf("%Zd",b);                                                                                                                                                                                                                    
                                                                                                                                                                                                                                             
    return 0;                                                                                                                                                                                                                                
}      

解决方法

下面的代码使用 mpz_fdiv_q_2exp 进行右移,使用 mpz_mul_2exp 进行左移以及 mpz_tdiv_r_2expmpz_tdiv_r_2exp 是必要的,因为随着数据的增加,大小也会增加。

#include <stdio.h>                                                                                                                                                                                                                           
#include <gmp.h>                                                                                                                                                                                                                             
                                 

int main()                                                                                                                                                                                                                                   
{                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                             
    mpz_t a;                                                                                                                                                                                                                                 
    mpz_t b;                                                                                                                                                                                                                                 
                                                                                                                                                                                                                                             
    mpz_init_set_str(a,"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",16);                                                                                                                                                                                  
              
    for ( int i = 0; i < 128;  i++) {
        
        //left shift
        mpz_mul_2exp(b,a,I);
        //This is faster than `mpz_mod` since we are in 2^128 
        mpz_tdiv_r_2exp(b,b,128);
        
        //right shift
        //mpz_fdiv_q_2exp( b,i);     
    
        gmp_printf("\n%#40Zx",b); 
    }
    
    gmp_printf("\n%Zd",a);
    
    return 0;                                                                                                                                                                                                                                
} 

部分输出

      0xffffffffffffffffffffffffffffffff
      0xfffffffffffffffffffffffffffffffe
      0xfffffffffffffffffffffffffffffffc
      ...
      0xe0000000000000000000000000000000
      0xc0000000000000000000000000000000
      0x80000000000000000000000000000000

GMP manual page 35

对于正 n,mpz_fdiv_q_2exp 和 mpz_tdiv_q_2exp 都是简单的按位右移。

注意:可以直接使用mpn_lshiftmpn_rshift,但是这需要在开发库下进行更多的编码和测试。从 mpz_mul_2exp 的源代码可以看出它的复杂程度。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。