1、使用位运算乘法。
把一个乘数变为2进制后,使用位运算完成乘数的乘法。
- /*
- * 输入:正整数k 和 正整数m
- * 输出:k*m
- */
- __int64 km(__int64 k, __int64 m){
- __int64 x = k;
- int w = (int)floor(log(m) / log(2)) -1;
- __int64 e = 1 << w;
- for(int i=0; i<=w; i++){
- x <<= 1;
- if(m & e)
- x += k;
- e >>= 1;
- }
- return x;
- }
2、使用位运算的乘方运算
指数变为2进制后,使用位运算完成乘方运算。
伪代码:
C++实现
- /*
- * 输入:正整数v mod m 和 g mod m
- * 输出:g^v mod m
- */
- __int64 gvmm(__int64 g, __int64 v, __int64 m){
- int w = (int)floor(log(v) / log(2)) - 1;
- __int64 e = 1 << w;
- __int64 x = g;
- for(int i=0; i<=w; i++){
- x = (x * x) % m;
- if(v & e){
- x = (g * x) % m;
- }
- e >>= 1;
- }
- return x;
- }
使用普通算法和位运算算法比较。
- #include <iostream>
- #include <math.h>
- #include <time.h>
- using namespace std;
- /*
- * 输入:正整数v mod m 和 g mod m
- * 输出:g^v mod m
- */
- __int64 gvmm(__int64 g, __int64 v, __int64 m){
- int w = (int)floor(log(v) / log(2)) - 1;
- __int64 e = 1 << w;
- __int64 x = g;
- for(int i=0; i<=w; i++){
- x = (x * x) % m;
- if(v & e){
- x = (g * x) % m;
- }
- e >>= 1;
- }
- return x;
- }
- /*
- * 验证结果的普通算法
- */
- int yanzheng(__int64 g, __int64 v, __int64 m){
- __int64 x = 1;
- for(int i=0; i<v; i++){
- x *= g;
- x %= m;
- }
- return x;
- }
- int main(){
- clock_t begin = clock();
- cout << yanzheng(23229,1892123, 23894) << endl;
- clock_t end = clock();
- double cost = (double)(end - begin) / CLOCKS_PER_SEC;
- printf("putong : %lf seconds\n", cost);
- begin = clock();
- cout << gvmm(23229,1892123, 23894) << endl;
- end = clock();
- cost = (double)(end - begin) / CLOCKS_PER_SEC;
- printf("weiyunsuan: %lf seconds\n", cost);
- system("pause");
- }
按照程序中给出的稍复杂的乘方运算,其效率分别为(多次测量后都差不多这个数量级)
21963
putong : 0.071000 seconds
21963
weiyunsuan: 0.001000 seconds
差不多普通算法比位运算算法慢了50-70倍。
原文地址:点击打开链接