高精度算法
1. 什么是高精度
高精度算法在一般的科学计算中,会经常算到小数点后几百位或者更多,当然也可能是几千亿几百亿的大数字.
一般这类数字我们统称为高精度数,高精度算法是用计算机对于超大数据的一种模拟加,减,乘,除,乘方,阶乘,开方等运算.
譬如一个很大的数字N >= 10^ 100, 很显然这样的数字无法在计算机中正常存储.
于是, 我们想到了办法,将这个数字拆开,拆成一位一位的 或者是四位四位的存储到一个数组中, 用一个数组去表示一个数字.这样这个数字就被称谓是高精度数.
对于高精度数,也要像平常数一样做加减乘除以及乘方的运算,于是就有了高精度算法:
下面提供了Pascal的高精度加法, 高精度乘以单精度, 高精度乘以高精度的代码, 其他版本请各位大牛添加进来吧!
Pascal代码如下(非完整); k为预定进制,加大进制以提高速度。
Procere HPule(a, b: Arr; Var c:Arr); //高精度加法
Var
i: Integer;
Begin
FillChar(c, SizeOf(c), 0);
For i:= 1 To Maxn-1 Do Begin
c[i]:= c[i] + a[i] + b[i];
c[i + 1] := c[i] Div k;
c[i] := c[i] Mod k;
End;
End;
Procere HPule(a: Arr; b:Integer; Var c:Arr); //高精度乘以单精度
Var
i: Integer;
Begin
FillChar(c, SizeOf(c), 0);
For i:= 1 To Maxn-1 Do Begin
c[i] := c[i] + a[i] * b;
c[i+1]:= c[i] Div k;
c[i]:= c[i] Mod k
End;
End;
Procere HPule(a, b: Arr; ; Var c:Arr); //高精度乘以高精度
Var
i, j: Integer;
Begin
FillChar(c, SizeOf(c), 0);
For i:= 1 To Maxn Do
For j := 1 To Maxn Begin
c[i+j-1] := c[i+j-1] + a[i] * b[j];
c[i+j]:= c[i+j-1] Div k;
c[i+j-1]:= c[i+j-1] Mod k
End;
End;
Ps:为了防止网络错误识别, 过程中有不少符号是全角状态输入.
高精度加法
var
a,b,c:array[1..201] of 0..9;
n:string;
lena,lenb,lenc,i,x:integer;
begin
write('Input augend:'); readln(n);lena:=length(n);
for i:=1 to lena do a[lena-i+1]:=ord(n)-ord('0');{加数放入a数组}
write('Input addend:'); readln(n); lenb:=length(n);
for i:=1 to lenb do b[lenb-i+1]:=ord(n)-ord('0');{被加数放入b数组}
i:=1;
while (i<=lena) or(i<=lenb) do
begin
x := a + b + x div 10; {两数相加,然后加前次进位}
c := x mod 10; {保存第i位的值}
i := i + 1
end;
if x>=10 {处理最高进位}
then begin lenc:=i; c:=1 end
else lenc:=i-1;
for i:=lenc downto 1 do write(c); writeln {输出结果}
end.
高精度乘法(低对高)
const max=100; n=20;
var a:array[1..max]of 0..9;
i,j,k;x:integer;
begin
k:=1; a[k]:=1;{a=1}
for i:=2 to n do{a*2*3….*n}
begin
x:=0;{进位初始化}
for j:=1 do k do{a=a*i}
begin
x:=x+a[j]*i; a[j]:=x mod 10;x:=x div 10
end;
while x>0 do {处理最高位的进位}
begin
k:=k+1;a[k]:=x mod 10;x:=x div 10
end
end;
writeln;
for i:=k dowento 1 write(a){输出a}
end.
高精度乘法(高对高)
var a,b,c:array[1..200] of 0..9;
n1,n2:string; lena,lenb,lenc,i,j,x:integer;
begin
write('Input multiplier:'); readln(n1);
write('Input multiplicand:'); readln(n2);
lena:=length(n1); lenb:=length(n2);
for i:=1 to lena do a[lena-i+1]:=ord(n1)-ord('0');
for i:=1 to lenb do b[lenb-i+1]:=ord(n2)-ord('0');
for i:=1 to lena do
begin
x:=0;
for j:=1 to lenb do{对乘数的每一位进行处理}
begin
x := a*b[j]+x div 10+c;{当前乘积+上次乘积进位+原数}
c:=x mod 10;
end;
c:= x div 10;{进位}
end;
lenc:=i+j;
while (c[lenc]=0) and (lenc>1) do dec(lenc); {最高位的0不输出}
for i:=lenc downto 1 do write(c); writeln
end.
高精度除法
fillchar(s,sizeof(s),0);{小数部分初始化}
fillchar(posi,sizeof(posi),0); {小数值的位序列初始化}
len←0;st←0; {小数部分的指针和循环节的首指针初始化}
read(x,y);{读被除数和除数}
write(x div y);{输出整数部分}
x←x mod y;{计算x除以y的余数}
if x=0 then exit;{若x除尽y,则成功退出}
while len<limit do{若小数位未达到上限,则循环}
begin
inc(len);posi[x]←len;{记下当前位小数,计算下一位小数和余数}
x←x*10; s[len]←x div y;x←x mod y;
if posi[x]<>0 {若下一位余数先前出现过,则先前出现的位置为循环节的开始}
then begin st←posi[x]; break;end;{then}
if x=0 then break; {若除尽,则成功退出}
end;{while}
if len=0
then begin writeln;exit;end;{若小数部分的位数为0,则成功退出;否则输出小数点}
write('.');
if st=0 {若无循环节,则输出小数部分,否则输出循环节前的小数和循环节}
then for i←1 to len do write(s)
else begin
for i←1 to st-1 do write(s);
write('(');
for i←st to len do write(s);
write(')');
end;{else}
2. 求一个高精度的GPS算法!
首先你要明白,你用GPS算出的点的数值和这个点的实际值是有误差的,这个误差的参数是多少,你必须知道,然后去做点校正。做好之后就是这个点的高精度数值,误差一般在厘米级。你的算法对不对我不好说,因为不清楚你的过程,但是知道这两个点的准确数值之后,肯定对你有帮助。
3. 高精度运算
// 无符号整数的高精度加减乘除运算
#include < stdio.h >
#include < string.h >
const int DEV = 10000 ; //定义每个整数存放大整数中四位(104)
const int MAXN = 1000 ; //最大整数长度 MAXN×4
struct BIG_INT {
int bit [ MAXN ], cnt;
bool positive ;
BIG_INT (){ cnt=0; positive = true ; memset ( bit , 0 , sizeof ( bit ) ); }
//-------------------------------------------------输入字符串,转化为大整数的表示
void Input () {
char ts[1000] ;
scanf ( "%s", ts);
int i = 0 , j = 0 , pt = 0 ;
int len = strlen (ts);
for ( i = len-1 ; i >=0 ; i -= 4 )
{
int temp = 0 ;
for ( j = ( i-3 >= 0)?i-3:0 ; j <= i; j++ )
temp = temp * 10 + ts[j] - '0';
bit[ pt++ ] = temp ;
}
cnt = pt ;
while ( cnt > 0 && bit [ cnt - 1 ] == 0 ) cnt -- ;
}
//------------------------------------------------输出大整数
void print () {
int i ;
if( cnt == 0 ) printf ( "%d\n", 0 );
else{
printf ( "%d", bit[cnt-1] );
for ( i=cnt-2 ; i >=0; i -- )
printf ( "%04d", bit );
printf ("\n") ;
}
}
//------------------------------------------------------加法
void add ( BIG_INT& fir, BIG_INT& sec ) {
cnt = 0 ;
int left = 0 ;
int pt = 0 ;
int temp = 0 ;
while ( pt < fir.cnt || pt < sec.cnt || left >0 ) {
temp = left ;
if ( pt < fir.cnt ) temp += fir.bit[pt] ;
if ( pt < sec.cnt ) temp += sec.bit[pt] ;
bit[ pt++ ] = temp%DEV ;
left = temp/DEV ;
}
cnt = pt;
}
// ----------------------------------减法,必须fir>sec !
void sub ( BIG_INT& fir, BIG_INT& sec ) {
cnt = 0 ;
int left = 0 ;
int pt = 0 ;
int temp = 0 ;
while ( pt < fir.cnt ){
temp = fir.bit[pt] - left ;
if ( pt < sec.cnt ) temp -= sec.bit[pt] ;
if( temp < 0){ temp += DEV; left = 1;}
else left = 0;
bit [pt++] = temp ;
}
cnt = pt ;
while ( bit[cnt-1] == 0 ) cnt-- ;
}
//---------------------------------乘法
void multiple ( BIG_INT& fir, BIG_INT& sec ) {
int i , j ;
cnt = 0 ;
memset ( bit , 0 ,sizeof ( bit ) );
int left = 0 ;
int temp = 0 ;
for ( i = 0 ; i < fir.cnt ; i++ )
{
left = 0 ;
for ( j = 0 ; j < sec.cnt ; j++ )
{
temp = left + fir.bit [ i ] * sec.bit [ j ] + bit [ i+j ];
bit [ i+j ] = temp % DEV ;
left = temp / DEV ;
}
while ( left > 0 )
{
temp = left + bit [ i+j ] ;
bit [ i+j ] = temp % DEV;
left = temp / DEV;
j++ ;
}
}
for ( i = MAXN - 1 ; i >= 0 ; i-- )
if ( bit [ i ] > 0) break;
cnt = i + 1 ;
}
// --------------------------------------比较fir与sec 大小
//--------------------------------------If ( fir < sec ) return true
bool smaller ( BIG_INT& fir, BIG_INT& sec){
while ( fir.cnt > 0 && fir.bit [ fir.cnt - 1 ] == 0 ) fir.cnt -- ;
while ( sec.cnt > 0 && sec.bit [ sec.cnt - 1 ] == 0 ) sec.cnt -- ;
if ( fir.cnt < sec.cnt ) return true;
else if ( fir.cnt > sec.cnt ) return false;
int i ;
for ( i = fir.cnt - 1 ; i >= 0 ; i -- ){
if ( fir.bit [ i ] < sec.bit [ i ] ) return true;
else if ( fir.bit [ i ] > sec.bit [ i ] ) return false;
}
return false;
}
// ----------------------------------------------返回 fir/sec 且fir = fir%sec
// -------------------------------------------- 供 devide 调用
int get_div ( BIG_INT& fir, BIG_INT& sec ){
int pt = 0 ;
BIG_INT tadd ;
while ( 1 ) {
if ( smaller ( fir, sec ) ) return pt ;
tadd.sub ( fir , sec );
fir = tadd ;
pt ++ ;
}
}
//-----------------------------------------------除法
void Devide ( BIG_INT& fir, BIG_INT& sec, BIG_INT& remd ) {
if( sec.cnt == 0 || ( sec.cnt == 1 && sec.bit [0] == 0 ) ) {
printf ( "Devide Error ! \n" ) ;
return ;
}
cnt = 0 ;
remd.cnt = 0;
memset ( bit , 0 , sizeof ( bit ) ) ;
memset ( remd.bit , 0 , sizeof ( remd.bit ) ) ;
int i , j ;
for ( i = fir.cnt - 1 ; i >= 0 ; i-- )
{
for ( j = remd.cnt - 1 ; j >= 0 ; j -- ) remd.bit [ j+1 ] = remd.bit [ j ] ;
remd.bit [ 0 ] = fir.bit [ i ] ;
remd.cnt ++ ;
int ret_n = get_div ( remd , sec ) ;
bit [ i ] = ret_n ;
}
for ( i = fir.cnt - 1 ; i >= 0 ; i-- )
if ( bit [ i ] > 0 ) break ;
cnt = i + 1 ;
}
};
//----------------------------------------------------调用参考
int main()
{
BIG_INT fir,sec,res;
while(1)
{
fir.Input();
sec.Input();
BIG_INT rem;
res.Devide ( fir , sec , rem );
res.print();
rem.print();
}
return 0;
}
4. 高精度计算 c语言
用字节数组,并自定义运算方法。不过至少要慢100倍。
5. 高精度加法的基本算法
以358934760892734899+38960302975237462为例:
1、计算结果的位数
358934760892734899共18位
38960302975237462共17位
故结果不会超过19位。
2、将要计算的数字分割成多段,按照顺序排列(这里以0-32767作为每一存储单位存储的数的限制): 35 8934 7608 9273 4899 3 8960 3029 7523 7462 (为提高空间利用效率,可以一个存储单位存储多位数。)
3、将两数相加。 35 8934 7608 9273 4899 3 8960 3029 7523 7462 和(不进位) 38 17894 10637 16796 12361 和(进位后) 39 7895 0638 6797 2361 4、输出结果。
从高位到低位依次输出。除最高位以外,其他低位上不足4位的要在前面补上0。
6. c语言高精度计算
不是我写的,,帮你找到的。。
#include<stdio.h>
#include<conio.h>
#include<string.h>
#include"stdlib.h"
voidmain()
{
intn=0,i=0,j=0,k=0,b=0;
chara[3][500]={0};
intn1=0,n2=0;
chars[500]={0};
intn3=0;
intc=0,c1=0;
inttemp=0;
charop;
charstr[1001]={0};
char*result;
scanf("%d",&n);
result=(char*)malloc(501*n);//根据输入的n申请内存空间
*result='