精华内容
下载资源
问答
  • 高精度计算

    2017-08-08 19:30:37
    高精度计算PPT
  • C++实现高精度计算类库,包含了FFT的乘法除法,开平方,用法类似java的bigint,实测速度比java的快很多
  • 高精度计算1

    2018-10-24 12:27:06
    高精度计算,包括高精度加减乘(如何存储大整数?如何实现?如何进位?)
  • 面向单纯形的高精度计算算法设计.pdf
  • 用于Visual studio 高精度计算库项目文件; 包括了gmp, mpir, mpfr, gmp, 等,可以直接在visual studio中编译成为静态或动态链接库,用于作超高精度数值计算时调用; 跟Eigen C++ tempalte library库和Pavel写的mpfr C++...
  • 高精度计算总结

    千次阅读 2020-04-12 20:35:29
    进度加法 void add(string aa,string bb){ la=aa.size(); lb=bb.size(); for(int i=0;i<la;i++){ a[la-i]=aa[i]-'0'; } for(int i=0;i<lb;i++){ b[lb-i]=bb[i]-'0'; } ...

    高进度加法

    void add(string aa,string bb){
        la=aa.size();
        lb=bb.size();
        for(int i=0;i<la;i++){
            a[la-i]=aa[i]-'0';
        }
        for(int i=0;i<lb;i++){
            b[lb-i]=bb[i]-'0';
        }
        lc=max(la,lb);
        for(int i=1;i<=lc;i++){
            c[i]+=(a[i]+b[i])%10;
            c[i+1]=(a[i]+b[i])/10;
        }
        if(c[lc+1]) lc++;
        for(int i=lc;i>=1;i--){
            cout<<c[i];
        }
    }
    

    高精度减法

    //相等返回0,大于返回1,小于返回-1
    int compare(string s1,string s2){
        if(s1.size()>s2.size()) return 1;
        else if(s1.size()<s2.size()) return -1;
        else return s1.compare(s2);//位数相同用compare函数进行比较
    }
    
    void sub(string aa,string bb){
        //比较大小
        if(compare(aa,bb)==-1){
            swap(aa,bb);
            cout<<"-";
        }
        else if(compare(aa,bb)==0){
            cout<<0; return;
        }
        la=aa.size();
        lb=bb.size();
        //string->int数组,低位排在前面
        for(int i=0;i<la;i++){
            a[la-i]=aa[i]-'0';
        }
        for(int i=0;i<lb;i++){
            b[lb-i]=bb[i]-'0';
        }
        //计算
        for(int i=1;i<=la;i++){
            if(a[i]<b[i]){
                a[i]+=10;
                a[i+1]--;
            }
            c[i]=a[i]-b[i];
        }
        //去除多余的0,la>1防止去掉全0的情况
        while(c[la]==0&&la>1) la--;
        for(int i=la;i>=1;i--){
            cout<<c[i];
        }
        }
    

    高精度乘法

    void mul(string a,string b){
        la=a.size();
        lb=b.size();
        //string->int数组,低位排在前面
        for(int i=0;i<la;i++){
            a[la-i]=x[i]-'0';
        }
        for(int i=0;i<lb;i++){
            b[lb-i]=y[i]-'0';
        }
        //乘法计算
        for(int i=1;i<=la;i++){//从1开始
            for(int j=1;j<=lb;j++){
                //别忘了+号,同一个结果为是多个乘积叠加的
                c[i+j-1]+=a[i]*b[j];
                c[i+j]+=c[i+j-1]/10;
                c[i+j-1]%=10;
            }
        }
        //计算结果的长度(消去没有用的),方便打印
        lc=la+lb;
        while(c[lc]==0&&lc>1){
            lc--;
        }
        //反向输出
        for(int i=lc;i>=1;i--){
            cout<<c[i];
        }
    }
    

    高精度除法

    //高精度除单精度
    string div(string a,int b)//高精度a除以单精度b
    {
        string r,ans;
        int d=0;
        if(a=="0") return a;//特判
        for(int i=0;i<a.size();i++)
        {			
        		//上一步余数*10相当与此时的被除数
                r+=(d*10+a[i]-'0')/b+'0';//求出商
                d=(d*10+(a[i]-'0'))%b;//求出余数
        }
        int p=0;
        for(int i=0;i<r.size();i++)
        if(r[i]!='0') {p=i;break;}
        return r.substr(p);
    }
    int main()
    {
        string a;
        int b;
        while(cin>>a>>b)
        {
            cout<<div(a,b)<<endl;
        }
        return 0;
    }
    
    

    高精度取模

    
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int mod(string a,int b)//高精度a除以单精度b
    {
        int d=0;
        for(int i=0;i<a.size();i++)  d=(d*10+(a[i]-'0'))%b;  //求出余数
        return d;
    }
    int main()
    {
        string a;
        int b;
        while(cin>>a>>b)
        {
            cout<<mod(a,b)<<endl;
        }
        return 0;
    
    

    高精度阶乘

    
    const int L=100005;
    int a[L];
    string fac(int n)
    {
        string ans;
        if(n==0) return "1";
        fill(a,a+L,0);
        int s=0,m=n;
        while(m) a[++s]=m%10,m/=10;
        for(int i=n-1;i>=2;i--)
        {
            int w=0;
            for(int j=1;j<=s;j++) a[j]=a[j]*i+w,w=a[j]/10,a[j]=a[j]%10;
            while(w) a[++s]=w%10,w/=10;
        }
        while(!a[s]) s--;
        while(s>=1) ans+=a[s--]+'0';
        return ans;
    }
    int main()
    {
        int n;
        while(cin>>n) cout<<fac(n)<<endl;
        return 0;
    }
    
    展开全文
  • 精确计算N的阶乘。其中,N可能是小于200的任意正整数。 【输入形式】 输入文件为当前目录下的factor.in。该文件只包含一个正整数,表示需要求该正整数的阶乘。 【输出形式】 输入文件为当前目录下...
  • Java高精度计算Java高精度计算Java高精度计算Java高精度计算Java高精度计算Java高精度计算Java高精度计算Java高精度计算Java高精度计算Java高精度计算Java高精度计算Java高精度计算
  • 关于高精度的基本运算,包括加减乘除和阶乘,是用c语言实现的,绝对的好东西
  • 第1章 高精度计算-2019-02-19
  • pt100高精度计算方法

    2013-06-28 12:28:58
    介绍一种采用恒压分压法精密测量三线制热电阻阻值的方法,对于Pt100热电阻,检测分辨率可以达到0.005W。同时采用计算的方法,能够使获得的温度准确度达到0.05℃。
  • JS的高精度计算(BigDecimal)

    热门讨论 2011-01-18 19:41:00
    你是否因为JS端的小数计算精度不足而发愁过呢 其实有个不错的资源可以利用。 引用附件的JS,就可以轻松搞定JS的计算问题了。 使用例 <!-- function //+ alert(new BigDecimal("10").add(new BigDecimal("3E+...
  • 浮点数高精度计算 bcadd— 2个任意精度数字的加法计算 bccomp— 比较两个任意精度的数字 bcdiv— 2个任意精度的数字除法计算 bcmod— 对一个任意精度数字取模 bcmul— 2个任意精度数字乘法计算 bcpow— 任意...

    浮点数高精度计算

    • bcadd — 2个任意精度数字的加法计算
    • bccomp — 比较两个任意精度的数字
    • bcdiv — 2个任意精度的数字除法计算
    • bcmod — 对一个任意精度数字取模
    • bcmul — 2个任意精度数字乘法计算
    • bcpow — 任意精度数字的乘方
    • bcpowmod — Raise an arbitrary precision number to another, reduced by a specified modulus
    • bcscale — 设置所有bc数学函数的默认小数点保留位数
    • bcsqrt — 任意精度数字的二次方根
    • bcsub — 2个任意精度数字的减法
    /**
     * Add two arbitrary precision numbers
     * @link https://php.net/manual/en/function.bcadd.php
     * @param string $left_operand <p>
     * The left operand, as a string.
     * </p>
     * @param string $right_operand <p>
     * The right operand, as a string.
     * </p>
     * @param int $scale [optional] <p>
     * This optional parameter is used to set the number of digits after the
     * decimal place in the result. If omitted, it will default to the scale
     * set globally with the {@link bcscale()} function, or fallback to 0 if
     * this has not been set.
     * </p>
     * @return string The sum of the two operands, as a string.
     * @since 4.0
     * @since 5.0
     * @since 7.0
     */
    function bcadd ($left_operand, $right_operand, $scale = 0) {}
    
    /**
     * Subtract one arbitrary precision number from another
     * @link https://php.net/manual/en/function.bcsub.php
     * @param string $left_operand <p>
     * The left operand, as a string.
     * </p>
     * @param string $right_operand <p>
     * The right operand, as a string.
     * </p>
     * @param int $scale [optional] <p>
     * This optional parameter is used to set the number of digits after the
     * decimal place in the result. If omitted, it will default to the scale
     * set globally with the {@link bcscale()} function, or fallback to 0 if
     * this has not been set.
     * </p>
     * @return string The result of the subtraction, as a string.
     * @since 4.0
     * @since 5.0
     * @since 7.0
     */
    function bcsub ($left_operand, $right_operand, $scale = 0) {}
    
    /**
     * Multiply two arbitrary precision numbers
     * @link https://php.net/manual/en/function.bcmul.php
     * @param string $left_operand <p>
     * The left operand, as a string.
     * </p>
     * @param string $right_operand <p>
     * The right operand, as a string.
     * </p>
     * @param int $scale [optional] <p>
     * This optional parameter is used to set the number of digits after the
     * decimal place in the result. If omitted, it will default to the scale
     * set globally with the {@link bcscale()} function, or fallback to 0 if
     * this has not been set.
     * </p>
     * @return string the result as a string.
     * @since 4.0
     * @since 5.0
     * @since 7.0
     */
    function bcmul ($left_operand, $right_operand, $scale = 0) {}
    
    /**
     * Divide two arbitrary precision numbers
     * @link https://php.net/manual/en/function.bcdiv.php
     * @param string $dividend <p>
     * The dividend, as a string.
     * </p>
     * @param string $divisor <p>
     * The divisor, as a string.
     * </p>
     * @param int $scale [optional] <p>
     * This optional parameter is used to set the number of digits after the
     * decimal place in the result. If omitted, it will default to the scale
     * set globally with the {@link bcscale()} function, or fallback to 0 if
     * this has not been set.
     * </p>
     * @return string|null the result of the division as a string, or <b>NULL</b> if
     * <i>divisor</i> is 0.
     * @since 4.0
     * @since 5.0
     * @since 7.0
     */
    function bcdiv ($dividend, $divisor, $scale = 0) {}
    
    /**
     * Get modulus of an arbitrary precision number
     * @link https://php.net/manual/en/function.bcmod.php
     * @param string $dividend <p>
     * The dividend, as a string.
     * </p>
     * @param string $divisor <p>
     * The divisor, as a string.
     * </p>
     * @param int $scale [optional] <p>
     * This optional parameter is used to set the number of digits after the
     * decimal place in the result. If omitted, it will default to the scale
     * set globally with the {@link bcscale()} function, or fallback to 0 if
     * this has not been set.
     * </p>
     * @return string|null the modulus as a string, or <b>NULL</b> if
     * <i>divisor</i> is 0.
     * @since 4.0
     * @since 5.0
     * @since 7.0
     * @since 7.2.0 scale param added, dividend/divisor no longer truncated
     */
    function bcmod ($dividend, $divisor, $scale = 0) {}
    
    /**
     * Raise an arbitrary precision number to another
     * @link https://php.net/manual/en/function.bcpow.php
     * @param string $base <p>
     * The base, as a string.
     * </p>
     * @param string $exponent <p>
     * The exponent, as a string. If the exponent is non-integral, it is truncated.
     * The valid range of the exponent is platform specific, but is at least
     * -2147483648 to 2147483647.
     * </p>
     * @param int $scale [optional] <p>
     * This optional parameter is used to set the number of digits after the
     * decimal place in the result. If omitted, it will default to the scale
     * set globally with the {@link bcscale()} function, or fallback to 0 if
     * this has not been set.
     * </p>
     * @return string the result as a string.
     * @since 4.0
     * @since 5.0
     * @since 7.0
     */
    function bcpow ($base, $exponent, $scale = 0) {}
    
    /**
     * Get the square root of an arbitrary precision number
     * @link https://php.net/manual/en/function.bcsqrt.php
     * @param string $operand <p>
     * The operand, as a string.
     * </p>
     * @param int $scale [optional]
     * @return string the square root as a string, or <b>NULL</b> if
     * <i>operand</i> is negative.
     * @since 4.0
     * @since 5.0
     * @since 7.0
     */
    function bcsqrt ($operand, $scale = null) {}
    
    /**
     * Set default scale parameter for all bc math functions
     * @link https://php.net/manual/en/function.bcscale.php
     * @param int $scale <p>
     * The scale factor.
     * </p>
     * @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure.
     * @since 4.0
     * @since 5.0
     * @since 7.0
     */
    function bcscale ($scale) {}
    
    /**
     * Compare two arbitrary precision numbers
     * @link https://php.net/manual/en/function.bccomp.php
     * @param string $left_operand <p>
     * The left operand, as a string.
     * </p>
     * @param string $right_operand <p>
     * The right operand, as a string.
     * </p>
     * @param int $scale [optional] <p>
     * The optional <i>scale</i> parameter is used to set the
     * number of digits after the decimal place which will be used in the
     * comparison.
     * </p>
     * @return int 0 if the two operands are equal, 1 if the
     * <i>left_operand</i> is larger than the
     * <i>right_operand</i>, -1 otherwise.
     * @since 4.0
     * @since 5.0
     * @since 7.0
     */
    function bccomp ($left_operand, $right_operand, $scale = 0) {}
    
    /**
     * Raise an arbitrary precision number to another, reduced by a specified modulus
     * @link https://php.net/manual/en/function.bcpowmod.php
     * @param string $base <p>
     * The base, as an integral string (i.e. the scale has to be zero).
     * </p>
     * @param string $exponent <p>
     * The exponent, as an non-negative, integral string (i.e. the scale has to be
     * zero).
     * </p>
     * @param string $modulus <p>
     * The modulus, as an integral string (i.e. the scale has to be zero).
     * </p>
     * @param int $scale [optional] <p>
     * This optional parameter is used to set the number of digits after the
     * decimal place in the result. If omitted, it will default to the scale
     * set globally with the {@link bcscale()} function, or fallback to 0 if
     * this has not been set.
     * </p>
     * @return string|null the result as a string, or <b>NULL</b> if <i>modulus</i>
     * is 0 or <i>exponent</i> is negative.
     * @since 5.0
     * @since 7.0
     */
    function bcpowmod ($base, $exponent, $modulus, $scale = 0) {}
    

    常用数值处理方案

    舍去法取整(向下取整)

    echo floor(5.1);
    //输出:5
    
    echo floor(8.8);
    //输出:8

    进一法取整(向上取整)

    echo ceil(5.1);
    //输出:6
    
    echo ceil(8.8);
    //输出:9

    普通四舍五入法

    echo round(5.1);
    //输出:5
    
    echo round(8.8);
    //输出:9
    
    //保留两位小数并且进行四舍五入
    echo round(5.123, 2);
    //输出:5.12
    
    echo round(8.888, 2);
    //输出:8.89
    
    //保留两位小数并且不进行四舍五入
    echo substr(round(5.12345, 3), 0, -1);
    //输出:5.12
    
    echo substr(round(8.88888, 3), 0, -1);
    //输出:8.88

    银行家舍入法

    四舍六入五考虑,五后非空就进一,五后为空看奇偶,五前为偶应舍去,五前为奇要进一。

    保留两位小数,例:

    • 1.2849 = 1.28 -> 四舍
    • 1.2866 = 1.29 -> 六入
    • 1.2851 = 1.29 -> 五后非空就进一
    • 1.2850 = 1.28 -> 五后为空看奇偶,五前为偶应舍去
    • 1.2750 = 1.28 -> 五后为空看奇偶,五前为奇要进一

    实现代码如下:

    echo round(1.2849, 2, PHP_ROUND_HALF_EVEN);
    //输出:1.28
    
    echo round(1.2866, 2, PHP_ROUND_HALF_EVEN);
    //输出:1.29
    
    echo round(1.2851, 2, PHP_ROUND_HALF_EVEN);
    //输出:1.29
    
    echo round(1.2850, 2, PHP_ROUND_HALF_EVEN);
    //输出:1.28
    
    echo round(1.2750, 2, PHP_ROUND_HALF_EVEN);
    //输出:1.28

     

    数值格式化(千位分组)

    应用于金额的展示,比如我们经常会看的银行卡余额。

    echo number_format('10000.98', 2, '.', ',');
    //输出:10,000.98
    
    echo number_format('340888999', 2, '.', ',');
    //输出:340,888,999.00

    扩展

    MySQL 浮点型字段

    在 MySQL 中,创建表字段时也有浮点数类型。

    浮点数类型包括单精度浮点数(float)和双精度浮点数(double)。

    同理,不建议使用浮点数类型!!!

    浮点数存在误差,当我们使用精度敏感的数据时,应该使用定点数(decimal)进行存储。

    展开全文
  • 根据模拟,穷举,高精度计算列举一系列典型问题,约瑟夫,回文数,大数加法。
  • ACM模拟与高精度计算

    2018-09-25 02:23:15
    ACM模拟与高精度计算,具有大量的例题以及对应的详尽的题解与参考标准程序,适合acm入门者,以及应对ccf考试以及算法面试等等,很好理解
  • 用C/C++实现基本高精度计算

    千次阅读 2020-11-23 14:57:09
    高精度计算 什么是高精度 高精度算法 高精度数的读写 高精度加法 高精度减法 高精度乘法 高精度除法及求余 (前置技能:小学数学知识,C语言基础) 什么是高精度 我们知道,C/C++在64位编译器中支持的环境下,其各种...

    (前置技能:小学数学知识,C语言基础)

    什么是高精度

    我们知道,C/C++在64位编译器中支持的环境下,其各种整型数据类型表示是有范围的。

    类型名             			 		  	  取值范围
    signed char        			   		     -128~127
    unsiged char					  	  	    0~255
    short int        			  	       -32768~32767
    int            		 			  -2147483648~2147483647
    unsigned int								0~4294967295
    long         	          		  -2147483648~2141483647
    unsigned long 								0~4294967295
    long long 	 		     -9223372036854775808~9223372036854775807
    unsigned long long 						    0~18446744073709551615
    

    尽管long long类型(或者在有些编译器中表示为__int64.注意int64前面有2个下划线)能表示的数已经相当大了,但和一些天文数字比起来,它连屏幕的一行都占不到。很多实际数学问题其实是long long也无法解决的。
    例如,围棋的走法有3的361次方,这个数字怎么显示出来?宇宙中原子的总和是10的80次方,怎么显示出来?这些都是语言本身的数据类型无法表示的。实际上,这些数字如果用二进制去储存的话,需要的空间也是特别大的。为了节约空间,同时让我们能够算出这些大数据,我们需要一种应用数组进行模拟计算的方法——高精度计算。

    高精度算法

    提醒:本博文该部分的所有代码均只用于展示计算原理,如果要整合在一起并进行更加复杂的符合操作,会产生诸多bug(其实直接复制粘贴任何一段都可能会有问题)总之就是,在这里找不到板子啦

    高精度数的读写

    1. 读入高精度数
      直观地输入一个高精度数时,我们需要存储一个有很多很多位的数字.
      如何存储?最直接的方法就是将它存入一个字符串.
      例如,我们可以这样:
    char str[100] = {""};//100表示数据可能的最大位数.
    scanf("%s, &str);
    

    这种输入方式再简单不过了,我们输入“43983926969436339448266492\n”
    则数据“43983926969436339448266492”就被存入其中了
    (提示:彩蛋数据)
    2. 存储高精度数
    现在,数据的读取完成了,我们应该如何处理这个数,让他变得方便于计算呢?
    我们不妨再设置一个数组,然后将输入的数逆序存入,也就是将str的最后一位存入数组a的第0位、将str的倒数第二位存入数组a的第1位……

    #include <string.h>
    
    int a[100] = {0};//100应该为这个数据可能的最大位数.
    for(int i = 0; i < strlen(str); ++i)
    	a[i] = str[strlen(str) - i - 1] - '0';
    

    这个时候就有人会问了:为什么要逆序存储?
    这是因为,数据的长度毕竟不确定,高精度计算既然是利用数组计算,应当是需要每一位每一位对齐再处理运算. 如果顺序存储,两个数长度不一样,最后一位的下标也不同,最后处理运算时最后一位不能直接对齐,还要经过一个移位的操作,显然加大了计算机的操作量. 反之,如果我们采取逆序存储的方式,存入的数组从第0位开始依次是个位、十位、百位……这些对应关系不会随着数据的长度改变而改变,有利于后面对两个高精度数进行运算.
    ——————————————————————————

    高精度加法

    了解了高精度的输入与存储后,我们可以定义一个表示高精度数据的结构体:

    #define LEN 1001//假定1001是我们处理的所有数据的最大位数
    
    struct hp{
        char str[LEN];
        int a[LEN];
    };
    

    为了进行加法,我们可以先准备3个结构体,分别作为两个加数和和. 注意定义后,为了正确输入并在后续输出时检查前导0, 应该将结构体的字符数组初始化为空串,将a数组全部初始化为0.

    void init(struct hp *x)//初始化函数
    {
    	for(int i = 0; i < LEN; ++i)
    	{
    		x->a[i] = 0;
    		x->str[i] = '\0';
    	}
    }
    

    如何进行高精度的加法?
    回想小学数学,那一个个竖式,逢十进一,简便美观的十进制表达……哦,我的上帝,多么纯粹简朴的方法啊!
    于是,高精度加法,其实就是基于竖式运算原理的啦~正因如此,我们才需要对齐两个加数.
    加法:
    先获取两个加数中最大的位数len,则本次加法计算需要进行len次操作. 从第0位开始,每次将对应位相加,得到和在该位的数值. 如果和在该位的数值大于等于10,那么将其减掉10,并让高一位加1.

    void add(struct hp x, struct hp y, struct hp *ans)
    {
        int len = 0;
        if(strlen(x.str) > strlen(y.str))
            len = strlen(x.str);
        else len = strlen(y.str);
        for(int i = 0; i < len; ++i)
        {
            ans->a[i] += x.a[i] + y.a[i];
            while(ans->a[i] >= 10)
            {
                ans->a[i] -= 10;
                ans->a[i + 1]++;
            }
        }
    }
    

    加法计算器完整代码:

    #include <stdio.h>
    #include <string.h>
    #include <math.h>
    #define LEN 1001//假定该程序处理的数据都是小于1000位的.
    /*最长位数1001是为了安全.*/
    
    struct hp{
        char str[LEN];
        int a[LEN];
    };//创建结构体hp(high-precision)
    //注意使用指针,这样来通过指针形参修改传入的实参.
    void init(struct hp *x)//hp初始化函数
    {
    	for(int i = 0; i < LEN; ++i)
    	{
    		x->a[i] = 0;
    		x->str[i] = '\0';
    	}
    }
    void in(struct hp *x)//输入函数.
    {
        scanf("%s", &x->str);
        int len = strlen(x->str);
        for(int i = 0; i < len; ++i)
            x->a[i] = x->str[len - i - 1] - '0';
    }
    void add(struct hp x, struct hp y, struct hp* ans)//加法函数
    {
        int len = 0;
        if(strlen(x.str) > strlen(y.str))
            len = strlen(x.str);
        else len = strlen(y.str);
        for(int i = 0; i < len; ++i)
        {
            ans->a[i] += x.a[i] + y.a[i];
            while(ans->a[i] >= 10)
            {
                ans->a[i] -= 10;
                ans->a[i + 1]++;
            }
        }
    }
    void show(struct hp ans)//输出函数
    {
        int j = LEN - 1;//数组有LEN位,其最后一个下标是LEN-1.
        while(ans.a[j] == 0 && j >= 1)
            --j;//跳过所有前导0.
            /*注:为了确保能输出结果0,前导0最多跳到第一位,
            不检查第0位是否为0,因此加了条件j >= 1.*/
           //现在,j的值是我们要输出的这个结果的最大位的下标.
        while(j >= 0)
        {
            printf("%d", ans.a[j]);
            --j;
        }
        printf("\n");
    }
    int main()
    {
        struct hp x, y, ans;
        init(&x);
        init(&y);
        init(&ans);
        in(&x);
        in(&y);
        add(x, y, &ans);
        show(ans);
        return 0;
    }
    
    

    以上就是进行高精度加法的过程了.


    高精度减法

    实现高精度减法,我们同样可以用三个结构体. 原理与加法相似,仍然是竖式原理:
    先获取被减数的位数len,则本次减法计算需要进行len次操作. 从第0位开始,每次将对应位相减,得到和在该位的数值. 如果和在该位的数值小于0,那么将其加上10,并让高一位减1.

     void minus(struct hp x, struct hp y, struct hp* ans)
    {
        int len = strlen(x.str);
        for(int i = 0; i < len; ++i)
        {
            ans->a[i] += x.a[i] - y.a[i];
            while(ans->a[i] < 0)
            {
                ans->a[i] += 10;
                ans->a[i + 1]--;
            }
        }
    }
    

    但是这样的减法是无法计算结果为负数的情况. 例如1 - 10.为了解决减法出现负数的问题,我们需要往结构体中添加一个表示正负的符号. 例如,添加一个bool值,并定义一个比较函数,利用其比较被减数和减数的大小(此处比较函数就交给你们啦). 当减数大于被减数,让设置的bool值为0,反之为1. 当bool值为1时直接进行减法运算. 如果bool值为0,就返回用减数减去被减数的结果.
    同样地,利用这个表示符号位的布尔值,我们还可以定义含有负数的加法,等等……


    高精度乘法

    要进行高精度乘法,我们会如何去操作?
    竖式乘法?我们很容易想到这样的方式:
    计算123 * 52,
    首先列竖式,让123乘以2,也就是让每一位乘以2,得到246.
    然后让123每一位乘以5,得到615(这里隐含了进位操作).
    最后,因为5是十位,它的位权是10,所以615修正为6150.
    让6150+246,得到结果6396.
    这个算法是可行的,让我们来看它的步骤应该如何设计:

    1. 首先获取被乘数和乘数的长度len1,len2;
    2. 定义len2个高精度数 a[len2],它们作为被乘数与乘数每一位分别相乘的结果;
    3. 每个 a[i] 拥有一个位权 j ,j 决定在后续处理中将所有 a[i] 相加时每个a[i] 要乘以10的幂数;
      (说白了就是为了模拟竖式乘法最后相加的过程)
    4. 取出乘数的第 i 位,让被乘数的每一位乘以这个数 ,并把乘得的结果存入a[i] 对应的位.
      (例如上方例子,123乘以5的时候,位权j为1,我们应当将结果15、 10、 5分别存入 a[1] 的第1(j + 0)位,第2(j + 1)位,第3(j + 2)位. 这里的a[1] 就是 {0,5,10,15} 了. 同理,我们知道 a[0] 为 {2,4,6}.)
    5. 最后一步和自然的竖式乘法的最后一步一致,让所有的 a[i] 相加. 因为我们在之前的讨论中已经封装了高精度的加法,并且进位判定都是用的while语句,因此无论 a[i] 的第几位有多大,最后相加的过程中也能利用进位得到正确结果了.

    代码实现:

    void multi(struct hp x, struct hp y, struct hp* ans)
    {
    	int len1 = strlen(x.str);
    	int len2 = strlen(y.str);
    	struct hp A[len2];//乘数有len2位.
    	/*这里应该还有一个使所有A.a[i]初始化为0的操作.
    	这里只展示乘法原理,略去.*/
    	for(int i = 0; i < len2; ++i)
            {
                //每个因子进i位.
                int n = y.a[i];//注意取n为被乘数的第i位.
                //让A[i]的每一位都乘上这个数.
                int u = i;
                for(int j = u; j < u + len1; ++j)
                    A[i].a[j] = x.a[j - u] * n;
            }
            //让所有因子相加.
            for(int i = 0; i < len2; ++i)
            {
            	struct hp tmp;
              	ans = add(ans, A[i], tmp);
            }
            return ans;
    }
    

    高精度除法及求余

    高精度除法的原理仍然是基于竖式除法……只不过,为了方便代码更加容易理解,我们不妨换一种方式解释.
    譬如,我们现在要计算1234除以9.

    1. 首先,获取最大位是4.将其减1得到3.
    2. 9乘以10的3次幂,得到9000.
    3. 用1234减去9000,结果小于0,有效的减法为0次. 在结果的千位放置0.
    4. 将9000降幂变为900,用1234减去900,得到334. 再减一个900,小于0. 有效的减法为1次,在结果的百位放置1.
    5. 将900降幂得到90,用334减去90,可以减3次,得到64. 有效的减法为3次,在结果的十位放置3.
    6. 将90降幂得到9,用64减去9,可以减7次,得到1.在结果的个位放置7.
    7. 9已经是9乘以10的零次幂了,最后这个1小于除数,那么我们除法得到的余数是1.
    8. 故:1234除以9等于137,余1.

    那么,我们将其转化为可以被机器执行的描述:

    1. 如果被除数的位数(len1)小于除数的位数(len2),直接返回0. (余数为被除数.)
    2. 否则的话,获取除数位数,让其乘以10的(被除数位数-除数位数)次方,得到一个数b.
    3. 定义一个长度最长为被除数位数数组cnt[len1].
    4. 将被除数减去b. 每减去一次b,cnt[位数]++.
    5. 当被除数即将在减去后小于0时,不执行该步减法,让b缩小为原来的十分之一.
    6. 继续减,直到b和原来的除数相等.

    该算法的实现依赖于高精度乘法和高精度减法,只有这两种计算方法已经封装了才可以实现除法. 另外,同样需要一个比较函数.
    利用这个算法,我们就可以求出两个数的商和余数了.

    感受:ACM的日子,每周还是要学点东西的~

    展开全文
  • 这个程序能计算任何精度的浮点数除法运算 加法,减法及乘法只能算整数类型的,但是可以是任何位数的运算。 程序全部采用的是手工的算法方法,与机器本身是没有关系的。运算结果比windows自带的计算器还哦!
  • C++为什么需要高精度计算

    千次阅读 2020-02-20 17:58:20
    为什么 C++ 需要高精度计算?这个问题对于 C++ 来说,是一个比较尴尬的问题。因为 Java 和 Python 是不需要高精度计算的,因为这两个语言直接支持高精度数据。 从 C++ 的角度回答这个问题,我们首先要从 C++ 的基础...

    为什么 C++ 需要高精度计算?这个问题对于 C++ 来说,是一个比较尴尬的问题。因为 Java 和 Python 是不需要高精度计算的,因为这两个语言直接支持高精度数据。

    从 C++ 的角度回答这个问题,我们首先要从 C++ 的基础知识来看,也就是 C++ 的数据类型可以表示的范围。下表是 C++ 常用的数据类型的字节大小和数值范围。我们针对 G++ 来说明这个问题,因为在不同类型的编译器里,相同数据类型的大小是不一样的。

    C++ 数据类型含义长度(Byte) 可以表示数值范围
    bool布尔类型1B true 或者 false
    short有符号短整型2B-2^15 ~ 2^15-1-32,768 ~ 32,767
    unsigned short无符号短整型2B0 ~ 2^16-10 ~ 65,535
    int有符号整型4B~2^31 ~ 2^31-1-2,147,483,648 ~ 2,147,483,647
    unsigned int无符号整型4B0 ~ 2^32-10 ~ 4,294,967,295
    long long有符号长整型8B-2^63 ~ 2^63-1–9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807
    unsigned long long无符号长整型8B0 ~ 2^64-10 ~ 18,446,744,073,709,551,615
    char有符号字符型1B-2^7 ~ 2^7-1-128 ~ 127
    unsigned char无符号字符型1B0 ~ 2^8-10 ~ 255
    float单精度浮点数4B 

    -3.4E-38 ~ 3.4E+38

    6 ~ 7位有效数据

    double双精度浮点数8B 

    -1.7E-308 ~ 1.7E+308

    15 ~ 16位有效数据

    long double长精度浮点数16B 

    -1.2E-4932 ~ 1.2E4932

    18 ~ 19位有效数据

    从上表,我们可以清楚的看到,当进行整数计算的时候, 数据超过 18,446,744,073,709,551,615,也就是超过 8Byte 后,C++就没有对应的数据类型就行表达。这就是为什么 C++ 需要高精度计算。

    展开全文
  • JAVA 高精度计算

    千次阅读 2019-05-08 20:25:39
    高精度计算 用cpp实现较为复杂 但对于java 的Biginteger 和 Big Decimal来说就容易许多了。 先来一道题: http://codeforces.com/gym/101848/problem/A 总结一下各种类型的精度: 对于超过18位的运算,及时long ...
  • 高精度计算--求n!的值
  • 针对工程实践中时常出现超高精度计算的程序设计需求,分析超高精度乘、除法运算规则,提出超高精度整数与普通整数的乘除法运算算法及两个超高精度整数的乘除法运算算法,并分别给出时间复杂度分析及实验数据。...
  • javascript高精度计算解决方案

    千次阅读 2017-09-27 21:16:03
    javascript高精度计算解决方案
  • 高精度计算pi(C语言)

    千次阅读 2021-03-26 14:29:58
    i++,t=t+2){//根据数学的知识,算的次数越多越精确 //i同时承担计数和做乘数的任务 //先计算乘法(即公式中R(n)*n) node* p3 = numtail; ret=0; while(p3) { temp = p3 -> date * i + ret; p3 -> date = temp%10; ...
  • 本篇文章主要介绍了Java使用BigDecimal进行高精度计算的示例代码,具有一定的参考价值,有兴趣的可以了解一下
  • 高精度计算(附高精度加法程序)

    千次阅读 2017-05-05 20:36:10
    高精度计算 有些数值计算要求精度高,希望计算的位数可达几十位甚至几百位,虽然计算机的计算精度也算较高了,但因受到硬件的限制,往往打不到实际问题所要求的精度,利用计算机处理高精度计算应注意以下问题: 数据...
  • C语言 高精度计算

    2012-04-17 16:23:03
    这是关于C语言 高精度运算的简单 概述

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 257,455
精华内容 102,982
关键字:

高精度计算