- 注册时间
- 2007-12-28
- 最后登录
- 1970-1-1
- 威望
- 星
- 金币
- 枚
- 贡献
- 分
- 经验
- 点
- 鲜花
- 朵
- 魅力
- 点
- 上传
- 次
- 下载
- 次
- 积分
- 12785
- 在线时间
- 小时
|
发表于 2017-1-15 17:36:33
|
显示全部楼层
仍然使用11楼的思想,做进一步优化。这个版本使用1次查表(表的大小为128个64bit数),2次比较,4次32位数乘法,10次32位数和64位数移位运算。
- #include <stdlib.h>
- #include <stdio.h>
- #include <limits.h>
- typedef int BOOL;
- #define TRUE 1
- #define FALSE 0
- typedef unsigned int uint32_t;
- #if defined(_MSC_VER)
- typedef unsigned __int64 uint64_t;
- #define RAD 1000000000ui64
- #define HALF_RAD 500000000ui64
- #define I64_1 1i64
- uint64_t prodArr[]=
- {
- 0ui64,
- 144115188000000000ui64,
- 288230376000000000ui64,
- 432345564000000000ui64,
- 576460752000000000ui64,
- 720575940000000000ui64,
- 864691128000000000ui64,
- 1008806316000000000ui64,
- 1152921504000000000ui64,
- 1297036692000000000ui64,
- 1441151880000000000ui64,
- 1585267068000000000ui64,
- 1729382256000000000ui64,
- 1873497444000000000ui64,
- 2017612633000000000ui64,
- 2161727821000000000ui64,
- 2305843009000000000ui64,
- 2449958197000000000ui64,
- 2594073385000000000ui64,
- 2738188573000000000ui64,
- 2882303761000000000ui64,
- 3026418949000000000ui64,
- 3170534137000000000ui64,
- 3314649325000000000ui64,
- 3458764513000000000ui64,
- 3602879701000000000ui64,
- 3746994889000000000ui64,
- 3891110078000000000ui64,
- 4035225266000000000ui64,
- 4179340454000000000ui64,
- 4323455642000000000ui64,
- 4467570830000000000ui64,
- 4611686018000000000ui64,
- 4755801206000000000ui64,
- 4899916394000000000ui64,
- 5044031582000000000ui64,
- 5188146770000000000ui64,
- 5332261958000000000ui64,
- 5476377146000000000ui64,
- 5620492334000000000ui64,
- 5764607523000000000ui64,
- 5908722711000000000ui64,
- 6052837899000000000ui64,
- 6196953087000000000ui64,
- 6341068275000000000ui64,
- 6485183463000000000ui64,
- 6629298651000000000ui64,
- 6773413839000000000ui64,
- 6917529027000000000ui64,
- 7061644215000000000ui64,
- 7205759403000000000ui64,
- 7349874591000000000ui64,
- 7493989779000000000ui64,
- 7638104968000000000ui64,
- 7782220156000000000ui64,
- 7926335344000000000ui64,
- 8070450532000000000ui64,
- 8214565720000000000ui64,
- 8358680908000000000ui64,
- 8502796096000000000ui64,
- 8646911284000000000ui64,
- 8791026472000000000ui64,
- 8935141660000000000ui64,
- 9079256848000000000ui64,
- 9223372036000000000ui64,
- 9367487224000000000ui64,
- 9511602413000000000ui64,
- 9655717601000000000ui64,
- 9799832789000000000ui64,
- 9943947977000000000ui64,
- 10088063165000000000ui64,
- 10232178353000000000ui64,
- 10376293541000000000ui64,
- 10520408729000000000ui64,
- 10664523917000000000ui64,
- 10808639105000000000ui64,
- 10952754293000000000ui64,
- 11096869481000000000ui64,
- 11240984669000000000ui64,
- 11385099857000000000ui64,
- 11529215046000000000ui64,
- 11673330234000000000ui64,
- 11817445422000000000ui64,
- 11961560610000000000ui64,
- 12105675798000000000ui64,
- 12249790986000000000ui64,
- 12393906174000000000ui64,
- 12538021362000000000ui64,
- 12682136550000000000ui64,
- 12826251738000000000ui64,
- 12970366926000000000ui64,
- 13114482114000000000ui64,
- 13258597302000000000ui64,
- 13402712491000000000ui64,
- 13546827679000000000ui64,
- 13690942867000000000ui64,
- 13835058055000000000ui64,
- 13979173243000000000ui64,
- 14123288431000000000ui64,
- 14267403619000000000ui64,
- 14411518807000000000ui64,
- 14555633995000000000ui64,
- 14699749183000000000ui64,
- 14843864371000000000ui64,
- 14987979559000000000ui64,
- 15132094747000000000ui64,
- 15276209936000000000ui64,
- 15420325124000000000ui64,
- 15564440312000000000ui64,
- 15708555500000000000ui64,
- 15852670688000000000ui64,
- 15996785876000000000ui64,
- 16140901064000000000ui64,
- 16285016252000000000ui64,
- 16429131440000000000ui64,
- 16573246628000000000ui64,
- 16717361816000000000ui64,
- 16861477004000000000ui64,
- 17005592192000000000ui64,
- 17149707381000000000ui64,
- 17293822569000000000ui64,
- 17437937757000000000ui64,
- 17582052945000000000ui64,
- 17726168133000000000ui64,
- 17870283321000000000ui64,
- 18014398509000000000ui64,
- 18158513697000000000ui64,
- 18302628885000000000ui64
- };
- #elif defined(__GNUC__)
- typedef unsigned long long uint64_t;
- #define HALF_RAD 500000000LL
- #define RAD 1000000000LL
- #define I64_1 1LL
- uint64_t prodArr[]=
- {
- 0LL,
- 144115188000000000LL,
- 288230376000000000LL,
- 432345564000000000LL,
- 576460752000000000LL,
- 720575940000000000LL,
- 864691128000000000LL,
- 1008806316000000000LL,
- 1152921504000000000LL,
- 1297036692000000000LL,
- 1441151880000000000LL,
- 1585267068000000000LL,
- 1729382256000000000LL,
- 1873497444000000000LL,
- 2017612633000000000LL,
- 2161727821000000000LL,
- 2305843009000000000LL,
- 2449958197000000000LL,
- 2594073385000000000LL,
- 2738188573000000000LL,
- 2882303761000000000LL,
- 3026418949000000000LL,
- 3170534137000000000LL,
- 3314649325000000000LL,
- 3458764513000000000LL,
- 3602879701000000000LL,
- 3746994889000000000LL,
- 3891110078000000000LL,
- 4035225266000000000LL,
- 4179340454000000000LL,
- 4323455642000000000LL,
- 4467570830000000000LL,
- 4611686018000000000LL,
- 4755801206000000000LL,
- 4899916394000000000LL,
- 5044031582000000000LL,
- 5188146770000000000LL,
- 5332261958000000000LL,
- 5476377146000000000LL,
- 5620492334000000000LL,
- 5764607523000000000LL,
- 5908722711000000000LL,
- 6052837899000000000LL,
- 6196953087000000000LL,
- 6341068275000000000LL,
- 6485183463000000000LL,
- 6629298651000000000LL,
- 6773413839000000000LL,
- 6917529027000000000LL,
- 7061644215000000000LL,
- 7205759403000000000LL,
- 7349874591000000000LL,
- 7493989779000000000LL,
- 7638104968000000000LL,
- 7782220156000000000LL,
- 7926335344000000000LL,
- 8070450532000000000LL,
- 8214565720000000000LL,
- 8358680908000000000LL,
- 8502796096000000000LL,
- 8646911284000000000LL,
- 8791026472000000000LL,
- 8935141660000000000LL,
- 9079256848000000000LL,
- 9223372036000000000LL,
- 9367487224000000000LL,
- 9511602413000000000LL,
- 9655717601000000000LL,
- 9799832789000000000LL,
- 9943947977000000000LL,
- 10088063165000000000LL,
- 10232178353000000000LL,
- 10376293541000000000LL,
- 10520408729000000000LL,
- 10664523917000000000LL,
- 10808639105000000000LL,
- 10952754293000000000LL,
- 11096869481000000000LL,
- 11240984669000000000LL,
- 11385099857000000000LL,
- 11529215046000000000LL,
- 11673330234000000000LL,
- 11817445422000000000LL,
- 11961560610000000000LL,
- 12105675798000000000LL,
- 12249790986000000000LL,
- 12393906174000000000LL,
- 12538021362000000000LL,
- 12682136550000000000LL,
- 12826251738000000000LL,
- 12970366926000000000LL,
- 13114482114000000000LL,
- 13258597302000000000LL,
- 13402712491000000000LL,
- 13546827679000000000LL,
- 13690942867000000000LL,
- 13835058055000000000LL,
- 13979173243000000000LL,
- 14123288431000000000LL,
- 14267403619000000000LL,
- 14411518807000000000LL,
- 14555633995000000000LL,
- 14699749183000000000LL,
- 14843864371000000000LL,
- 14987979559000000000LL,
- 15132094747000000000LL,
- 15276209936000000000LL,
- 15420325124000000000LL,
- 15564440312000000000LL,
- 15708555500000000000LL,
- 15852670688000000000LL,
- 15996785876000000000LL,
- 16140901064000000000LL,
- 16285016252000000000LL,
- 16429131440000000000LL,
- 16573246628000000000LL,
- 16717361816000000000LL,
- 16861477004000000000LL,
- 17005592192000000000LL,
- 17149707381000000000LL,
- 17293822569000000000LL,
- 17437937757000000000LL,
- 17582052945000000000LL,
- 17726168133000000000LL,
- 17870283321000000000LL,
- 18014398509000000000LL,
- 18158513697000000000LL,
- 18302628885000000000LL
- };
- #else
- #error do not support this compiler
- #endif
- void output_table()
- {
- uint64_t i,n,q,prod;
- uint64_t imax,max;
- uint64_t low57bits=(I64_1 << 57)-I64_1;;
-
- printf("uint64_t prodArr[]=\n{\n");
- for (max=0,i=0;i<128;i++)
- {
- n=( i << 57);
- q= n / RAD;
- prod=q * RAD;
- printf("\t%I64u,\n", prod);
- imax= n + low57bits- prod;
- if (imax>max)
- max=imax;
- }
- printf("};\n");
- // printf("\nmax remainder =%I64u",max);
- //max remainder =144115189068469759
- }
- /*
- 1. 关于 计算 a/10^9
- a/10^9 = a * 10^-9= (a * 2199.023255552) / 2^41,故我们采用2种方法来近似计算 q= a/(10^9)
- 方法1.
- u32_q =(uint32)(x>>37);
- u32_q *= 2199;
- u32_q >>= 17;
- u64_q = (uint64_t)u32_q
- u64_q <<= 13
-
- 方法2.
- u32_q =(uint32)(a>>23)
- u32_q *= 2199
- u32_q >>=18
-
- 2. 关于 计算 u32_q * 10^9
- 当u32_q <= 29820, 可使用下面的方法 计算u64_x= u32_q * 10^9
- u32_prod= u32_q * 144027
- u64_t1=(uint64_t)u32_q
- u64_t2=(uint64_t)u32_prod
- u64_x= (u64_t1<<30) - (u64_t2<<9)
- */
- uint32_t Uint64ModBillion(uint64_t a)
- {
- int i;
- uint64_t u64_t1,u64_t2,u64_prod;
- uint32_t u32_q,u32_prod;
- // step1
- i =(int) (a >> 57);
- // 根据最高7bit idx,找到一个值 x= prodArr[i], 使得 prodArr[i]是10^9的倍数,且prodArr[i]>=a
- a -= prodArr[i]; //至此,a的最大值为 144115189068469759= 1.0000000068876424494379584473336 * 2^57
- // step2
- u32_q=(uint32_t)(a >>37); // max(u32_q)= max(a)/2^37=144115189068469759/2^37=1048576
- u32_q *= 2199; // max(u32_q)= 1048576*2199=2305818624 < 2^32
- u32_q >>=17; // max(u32_q)= (1048576*2199) >>17 =17592 < 29820
- //误差分析
- //这里 u32_q 约等于 int((a/10^9)/2^13),
- //若 q=(a/10^9)/2^13, 则 max(a-u32_q) <= 1+ max(a)/(2^54)*0.023255552= 1+0.1860= 1.1860
-
- u32_prod = u32_q * 144027;
- u64_t1 = (uint64_t)u32_q;
- u64_t2 = (uint64_t)u32_prod;
- u64_prod = (u64_t1<<30) - (u64_t2<<9); // u64_prod= (uint64_t)u32_q * 10^9
- a-= (u64_prod<<13);
-
- // 这里a的最大值= (2^37-1)+1.1860*(2^13)*(10^9)= 9853514819840<2^44
-
- // step3
- u32_q=(uint32_t)(a >>23); // max(u32_q)= max(a)/2^23=9853514819840/2^23 = 1174630
- u32_q *= 2199; // max(u32_q)= 1174630*2199=2583011370 < 2^32
- u32_q >>=18; // max(u32_q)= (2583011370>>18)=9853 < 29820
-
- u32_prod = u32_q * 144027;
- u64_t1 = (uint64_t)u32_q;
- u64_t2 = (uint64_t)u32_prod;
- u64_prod = (u64_t1<<30) - (u64_t2<<9); // u64_prod= (uint64_t)u32_q * 10^9
- a-= u64_prod;
- //误差分析
- //这里 u32_q 约等于 int((a/10^9))
- //若q=(a/10^9), 则 max(a-u32_q)<= 1+ max(a)/(2^41)*0.023255552= 1+0.1042= 1.1042
- // 这里a的最大值= (2^23-1)+1.1042*(10^9)= 1112588607
- if ( a>=RAD) //因为a的最大值为1112588607,故只需调整余数一次
- a-=RAD;
- return (uint32_t)a;
- }
- int main(int argc, char* argv[])
- {
- uint64_t a;
- uint32_t mod;
-
- //output_table();
- a=9223372036854775807I64;
- mod=Uint64ModBillion(a);
- if ( mod >=HALF_RAD)
- printf("TRUE");
- else
- printf("FALSE");
- return 0;
- }
复制代码 |
|