字大小数据 - 快速取模的C++实现
本代码基于Barrett算法,加速32比特以内数据的模乘运算,以及64比特以内数据的取模运算。
- 小工具:
#pragma once#include <chrono>typedef char int8;
typedef int int32;
typedef long long int64;
typedef unsigned char uint8;
typedef unsigned int uint32;
typedef unsigned long long uint64;// 异常
#define ErrorInfo(format, ...) {\printf("File:%s, Line:%d, Function:%s, ",\__FILE__, __LINE__ , __FUNCTION__);\printf(format, ##__VA_ARGS__);}// 计时器
typedef std::chrono::steady_clock clock_type;//标准时钟:steady_clock。高分辨率时钟:high_resolution_clock
extern std::chrono::time_point<clock_type> TM_start, TM_end;
#define Clock() clock_type::now()
#define Time(t_start,t_end) std::chrono::duration<double, ratio<1, 1>>(t_end - t_start).count() //时间差,类型 double, s
#define Timer(code) TM_start = Clock(); code; TM_end = Clock(); std::cout << Time(TM_start,TM_end) << " s\n"; //对code部分计时// 循环测试
#define Loop(loop, code) Timer(for(int64 i=0;i<loop;i++) {code;})// 换行
#define pn puts("")
- Barrett算法实现:
#define WordLen 32 //Word = 2^WordLen,用于Barrett模乘
#define WordMod (((uint64)1L<<WordLen)-1) //Word - 1
#define TwiceWordLen 64 //用于Barrett模约简/*Barrett Reduction:T mod p = T - floor(T/p)*p选取Beta = 2^k,近似T/p = T'/Beta,得到:T' = T*Beta/p计算时,Q = T'/Beta则:T mod p = T - Q*pBarrett MulMod:若T = x*y mod p,且y和p都固定,那么可以预计算:y' = y*Beta/p计算时,Q = x*y'/Beta则:T mod p = x*y - Q*p由于Beta = 2^k,从而乘除法和取模都是位运算选取k=32,要求p的大小不超过32比特,p != 2
*//*预计算,Barrett模乘p,y < 2^32
*/
inline uint64 PreCompute(uint64 y, uint64 p)
{return (y << WordLen) / p;
}/*预计算,Barrett模约简p < 2^31
*/
inline uint64 PreComputeMod(uint64 p)
{//(1 << TwiceWordLen) / p;return (((uint64)1 << (TwiceWordLen - 1)) / p) << 1;
}/*Barrett模乘算法p < 2^31,输入输出在[0,2p)之间,冗余表示
*/
#define MulMod(x, y, y_pre, p) ((x) * (y) - (((x)*(y_pre)) >> WordLen) * p)/*Barrett模约简算法使用MulMod,选取y=1其中x = a*b < 4*p^2 < 2^64
*/
#define Mod(x, one_pre, p) ((x) - \
((x >> WordLen) * (one_pre >> WordLen) + \
(((x >> WordLen)*(one_pre & WordMod) + (one_pre >> WordLen) * (x & WordMod)) >> WordLen)) * p)
- 测试:
int main()
{uint64 pp = 8404993;uint64 ww = 12345;uint64 ww_pre = PreCompute(ww, pp);uint64 one_pre = PreComputeMod(pp);uint64 x = (uint64)1 << 20;uint64 y = (uint64)1 << 50;uint64 a=0, b=0;cout << x * ww%pp << " -> " << MulMod(x, ww, ww_pre, pp) << endl;cout << y%pp << " -> " << Mod(y, one_pre, pp) << endl;//Barrett算法,约比"%"算符快4倍!Loop(10000000, a=MulMod(x, ww, ww_pre, pp));Loop(10000000, b=x*ww%pp);Loop(10000000, a=Mod(y, one_pre, pp));Loop(10000000, b=y%pp);return 0;
}
- 测试结果(Debug, x64)
981500 -> 981500
540177 -> 540177
0.0511806 s
0.215115 s
0.05608 s
0.189529 s
在x86环境下,Barrett算法比%算符慢3倍。
字大小数据 - 快速取模的C++实现相关推荐
- 阶乘计算之大数阶乘与快速取模阶乘计算
大数阶乘的常规运算 即数学的模拟运算.一位一位的乘,有进位就进位. #include <bits/stdc++.h> #define _xx ios_base::sync_with_std ...
- 逐位相加法-快速取模算法
任意两个整数 A B 做乘法 C = A×B 然后把 A,B, C的十进制每个数分别相加,如果和大于10就继续把每个数相加,直到只剩一位数,分别得到 A1 B1 C1 D = A1 × B1,对D也进 ...
- 分区取模分库分表策略:多表事务分库内闭环解决方案
简介: 当表数据超过一定量级,就需要通过分表来解决单表的性能瓶颈问题:当数据库负载超过一定水平线,就需要通过分库来解决单库的连接数.性能负载的瓶颈问题.本文将阐述在不同情况下,让不同数量级表,在同一个 ...
- 0.96寸OLED显示汉字,数字,英文,图片,GIF动画+取模软件使用+代码解析
前言 本次我们学习一下STM32F103关于OLED显示汉字,数字,英文,图片,GIF动画,和介绍各种取模软件的使用,主要教会大家使用和修改OLED驱动的代码,对汉字大小,图片分辨率进行代码修改并显示 ...
- mycat分表之ER表分片、范围分片、取模分片、日期分片、全局表等
概述 数据库进行水平分表时,需要按照一定规则对数据进行分片. Mycat的分片策略可以分为两种: 连续分片和离散分片. 连续分片常用的有分片规则有: 范围分片. 日期分片. 优点:如果进行范围查询,比 ...
- mysql 取模分区_MySQL分区
分表是将一个大表按照一定的规则分解成多张具有独立存储空间的实体表,app读写的时候根据事先定义好的规则得到对应的子表名,然后去操作它.而分区是将数据分段划分在多个位置存放,分区后,表面上还是一张表,但 ...
- HDU 1212 大整数的取模运算
因为这里是MOD最大为100000 所以我将字符串看作5个一组,并记录后面跟了多少个100000 每次取5个数根据其数据进行取模更新 注意过程中 100000*100000会超int #include ...
- c语言float可以 取余吗,C语言fmod()函数:对浮点数取模(求余)
头文件:#include fmod() 用来对浮点数进行取模(求余),其原型为: double fmod (double x); 设返回值为 ret,那么 x = n * y + ret,其中 n 是 ...
- mysql分库分表取模扩容_MyCat分库分表策略——范围取模
范围取模分片的优点在于,既拥有范围分片的固定范围数据不做迁移的优点,也拥有了取模分片对于热点数据均匀分布的优点.首先我们还是以一个示例进行讲解: id rang-mod 0 files/partiti ...
- C语言fmod()函数:对浮点数取模(求余)和%取余运算符的比较
头文件:#include <math.h> fmod() 用来对浮点数进行取模(求余),其原型为: double fmod (double x); 设返回值为 ret,那么 x = ...
最新文章
- 你真的明确知道它们的用法吗-从基础学起
- 普通话测试第四题评分标准_普通话考试中命题说话的扣分标准
- 给 COLA 做减法:应用架构中的“弯弯绕设计”
- POJ 1088(滑雪)
- 走进武汉,探索多媒体开发最佳实践
- py06-python基础-字典
- java实验四——找鞍点
- jdk 取整数_JDK 15中的确切绝对整数
- spring 集成 Hibernate4.3.X org.hibernate.service.jta.platform.spi.JtaPlatform异常
- 基于Vue实现魔方矩阵排列效果
- Mac美化,GeekTool获取Yahoo天气图片
- 易基因|RNA m6A甲基化测序(MeRIP-seq)技术介绍
- ensp路由器MTU设置1200后,ping不通丢包问题
- 升级你的 Flutter 版本
- 大前端进阶!NodeJS、Npm、Es6、Babel、Webpack、模块化开发
- VBA 等待1S 处理方法
- 【什么情况下U盘会出现0字节?】
- 虚拟机连接不上网络的解决方案
- 无线网络***(-)
- Transformer课程 业务对话机器人Rasa 3.x Fallback and Human Handoff