问题来源与多核程序设计的作业,尽可能并行计算高精度的pi值,就想拿个数组模拟一下,因为担心double的精度不够
计算pi的方法如下:
然后就是计算的过程,小数这东西真的不好处理,从方向上来说可以双向延伸,和xq讨论了下,突然想到把指数带进来,就是科学计数法的表示,但是不要求那么严格,限定有效数字(后面称为系数)的范围,我想把系数变成整数,就不用考虑小数点的事了
然后运算全部是整数参与运算,就是大数而已,这种模拟已经写过,把问题转变了熟悉的模型,然后开始入坑了.....
自定义新数据类型如下:
typedef struct sint{
int digit[MAX]; //digit 0代表最低位,万进制加速运算
int len; //代表系数长度
int index;//代表指数(10进制)
sint(){len=0;memset(digit,0,sizeof(digit));index=0;}
}sint;
万进制,每个int储存4位数字(首位除外)
举例 : 1.630523 表示成 digit[0]=0523=523 digit[1]=163,len=1,index=-6
这种模拟运算最麻烦的是乘除,有了指数之后,乘除方便多了,虽然加减要对齐了
加减
a*10^b+c*10^d, 首先要对阶,我把指数大的转化成指数小的,这样也是保证系数是整数,大的变小,指数减小,系数左移就行了
所以移位操作也是要支持的,整个数组都要移动,代价太大了...
乘
a*10^b*c*10^d=a*c*10^(b+d) 用大数来乘就好了
除
浮点数最麻烦的就是除了
a*10^b/(c*10^d)
除发采用试除,需要不断保证系数a>b,小了就减少指数,我采用的一直往下除,直到小数点后100位,虽然可以支持上限到400,当然可以根据需要,定义digit数组的长度来改变
模拟人的计算,先找到最大的c,c*b<a,然后a-c*b=d,ans+=d 不断重复这个过程,直到a-c*b=0 或者到了小数点后100位
然后是c的确定,采用的是a的首位除以(b的首位+1),举个例子,62/27,直接拿6/3=2,c就是2,你会举出这样的反例,90/10,这样得到的不准确
没关系,因为不是算一次,如果判断首位相等,c就是1了,因为a系数始终大于b,然后继续迭代,小于的话就左移,指数减小就行了
然后是移位
比较坑的是输出浮点数
输出之前首先规格化,保证系数末尾不能有0,有就调整到指数上,这样就是右移了,但是这样可以解决不少麻烦
因为拿int储存的数据,万进制,有时候1代表的就是1,有时又代表的是0001
输出时先规格化,然后计算系数长度,是位数,和len不同,然后比较指数确定小数点的位置,然后逐位输出
这个东西虽然思路看上去不难,但是确实折腾人,写完感觉也是挺有收获,代码能力仍需加强
然后是全部代码,有空再详细一点描述mpi并行化与其它的一些细节
#include<iostream>
#include<cstdio>
#include<memory.h>
#include<sstream>
#include<math.h>
#include<cstdlib>
#define MAX 100
#define mod 10000
using namespace std;
typedef struct sint{
int digit[MAX]; //digit 0代表最低位
int len; //代表系数长度
int inde