高精度计算----减法运算(浮点型)

2024-09-07 19:18

本文主要是介绍高精度计算----减法运算(浮点型),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

基于上一贴,修改减法运算适合于高精度浮点型计算。

因为减法比加法难度大一点,考虑的地方也要多一些,可能代码有欠缺,欢迎指出。

运算说明:

1、相减函数依旧没改变,包括上一贴的判断被减数与减数的大小函数也没变。

2、增加两个函数,取小数位数函数和结果处理(回归小数点)函数

3、与加法浮点高精度运算相比,这里改变较多的是结果处理函数,加法加完后,位数不减反增,而且最多增一位。减法会消失掉好多位,对于浮点型,即小数点后面的数,又得把零补回来,故函数增加了几个判断,具体看代码的注释说明。

程序测试效果如下:

以下代码包含四个函数功能,皆有注释:

[cpp] view plain copy print ?
  1. #include "stdio.h"   
  2. #include "string.h"   
  3.   
  4. /************************************************************************/  
  5. /* 高精度减法    (这个函数要a[]>=b[])                                   */  
  6. /* a[]被减数数组,位数不限                                              */  
  7. /* b[]减数数组,位数不限                                                */  
  8. /* back[]结果数组,位数不会大于a[]数组的                                */  
  9. /************************************************************************/  
  10. void sub(char a[],char b[],char back[])  
  11. {  
  12.     int i,k,l1,l2;  
  13.     l1=strlen(a);  
  14.     l2=strlen(b);  
  15.     back[l1]='/0';  
  16.     for (i=l2-1,l1--;i>=0;l1--,i--)                //减数的个数小于等于被减数,所以减的次数依减数而定   
  17.     {  
  18.         if (a[l1]-b[i]>=0)                         //不需要借位相减   
  19.         {  
  20.             back[l1]=a[l1]-b[i]+'0';  
  21.         }  
  22.         else                                       //向前一位借1   
  23.         {  
  24.             back[l1]=10+a[l1]-b[i]+'0';  
  25.             if (a[l1-1]!='0')                      //当前一位非0,可以被借时,直接借来   
  26.             {  
  27.                 a[l1-1]-=1;  
  28.             }  
  29.             else                                   //若前一位为0,则无法借到,继续向前一位的前一位借,循环   
  30.             {  
  31.                 k=l1-1;  
  32.                 while (a[k]=='0')  
  33.                 {  
  34.                     a[k]='9';                      //前一位的0,就变成了10,扣去被后一位借去的,还有9   
  35.                     k--;  
  36.                 }  
  37.                 a[k]-=1;                           //到达可以借的位置   
  38.             }  
  39.         }  
  40.     }  
  41.     while (l1>=0)                                  //被减数多于减数的位数直接赋给结果数组   
  42.     {  
  43.         back[l1]=a[l1];  
  44.         l1--;  
  45.     }  
  46.     while (back[0]=='0')                           //将结果数组往前移,方便以后的操作   
  47.     {  
  48.         l1=strlen(a);  
  49.         for (i=0;i<l1-1;i++)  
  50.         {  
  51.             back[i]=back[i+1];  
  52.         }  
  53.         back[l1-1]='/0';  
  54.     }  
  55.     if (strlen(back)==0)                            //被减数与减数刚好相减为0的情况   
  56.     {  
  57.         back[0]='0';  
  58.         back[1]='/0';  
  59.     }  
  60. }  
  61.   
  62. /************************************************************************/  
  63. /* 判断函数(被减数与减数的大小比较)                                   */  
  64. /* 可以用strcmp函数比较字符串                                           */  
  65. /* 比较完后,若小于减数,则置换带入高精度减法函数,最后加'-'输出        */  
  66. /************************************************************************/  
  67. bool isBigger(char a[],char b[])  
  68. {  
  69.     int l1,l2;  
  70.     l1=strlen(a);  
  71.     l2=strlen(b);  
  72.     if (l1>l2)  
  73.     {  
  74.         return true;  
  75.     }  
  76.     else if (l1<l2)  
  77.     {  
  78.         return false;  
  79.     }  
  80.     else  
  81.     {  
  82.         if (strcmp(a,b)>=0)  
  83.         {  
  84.             return true;  
  85.         }  
  86.         else  
  87.         {  
  88.             return false;  
  89.         }  
  90.     }  
  91. }  
  92.   
  93. /************************************************************************/  
  94. /* 函数功能:返回小数点后的个数,并修改a,b数组为正整型                 */  
  95. /* 先找出小数点的位置,比较小数点后的个数,返回比较大的个数,不足的那个补0 */  
  96. /************************************************************************/  
  97. int decimal(char a[],char b[])  
  98. {  
  99.     int i,j,k,l1,l2;  
  100.     l1=strlen(a);  
  101.     l2=strlen(b);  
  102.     for (i=0;i<l1;i++)  
  103.     {  
  104.         if (a[i]=='.')                    //找到小数点位置,然后删除小数点   
  105.         {  
  106.             for (k=i;k<l1;k++)  
  107.             {  
  108.                 a[k]=a[k+1];  
  109.             }  
  110.             l1--;                         //长度减少   
  111.             break;  
  112.         }  
  113.     }  
  114.     for (j=0;j<l2;j++)  
  115.     {  
  116.         if (b[j]=='.')  
  117.         {  
  118.             for (k=j;k<l2;k++)  
  119.             {  
  120.                 b[k]=b[k+1];  
  121.             }  
  122.             l2--;  
  123.             break;  
  124.         }  
  125.     }  
  126.     k=(l1-i)-(l2-j);                        //比较两个数组谁的小数位更多   
  127.     if (i==l1 && j==l2)                     //都没有小数点的话,返回0   
  128.     {  
  129.         return 0;  
  130.     }  
  131.     else if (k>=0)                           //被减数更多,b[]数组后面对齐补0   
  132.     {  
  133.         while (k!=0)  
  134.         {  
  135.             b[l2++]='0';  
  136.             k--;  
  137.         }  
  138.         return l1-i;                          //返回a[]的小数位数   
  139.     }  
  140.     else if (k<0)                             //减数更多,a[]数组后面对齐补0   
  141.     {  
  142.         k=k*-1;                               //记住k要变为正的   
  143.         while (k!=0)  
  144.         {  
  145.             a[l1++]='0';  
  146.             k--;  
  147.         }  
  148.         return l2-j;  
  149.     }  
  150. }  
  151.   
  152. /************************************************************************/  
  153. /* 处理结果数组                                                         */  
  154. /* 将数组小数点后面的后移,插入小数点                                    */  
  155. /* 处理小数点某位0的情况,要去掉,若是小数点后不含任何数,小数点也要去掉   */  
  156. /************************************************************************/  
  157. void result(char c[],int n)  
  158. {  
  159.     int i,j,k,length;  
  160.     length=strlen(c);  
  161.     if (length==1 && c[0]=='0')                     //结果为0的话,不再处理,直接退出   
  162.     {  
  163.         return ;  
  164.     }  
  165.     if (length<n)                                   //结果的长度小于小数位数,则前面不止要补小数点还得补0   
  166.     {  
  167.         j=n+2;  
  168.         for (i=length-1;i>=0;i--)  
  169.         {  
  170.             c[--j]=c[i];  
  171.         }  
  172.         c[0]='0';  
  173.         c[1]='.';  
  174.         for (i=2;i<j;i++)  
  175.         {  
  176.             c[i]='0';  
  177.         }  
  178.     }  
  179.     else                                              //结果长度大于等于小数点,插入小数点即可(等于时再补个0)   
  180.     {  
  181.         for (i=length;i>length-n;i--)                 //数组后移length-n大小   
  182.         {  
  183.             c[i]=c[i-1];  
  184.         }  
  185.         c[length-n]='.';                              //插入小数点   
  186.         for (i=length;i>=length-n;i--)  
  187.         {  
  188.             if (c[i]!='0' && i!=length-n)             //当不在小数点上面的时候,不为0直接退出   
  189.             {  
  190.                 break;  
  191.             }  
  192.             else                                       //将0置为结束符,包括特定情况时去掉小数点   
  193.             {  
  194.                 c[i]='/0';  
  195.             }  
  196.         }  
  197.         length=strlen(c);  
  198.         if (c[0]=='.')                                  //小数点在第一位的话要后移,左补0   
  199.         {  
  200.             for (i=length;i>0;i--)  
  201.             {  
  202.                 c[i]=c[i-1];  
  203.             }  
  204.             c[0]='0';  
  205.         }  
  206.     }  
  207. }  
  208.   
  209. /************************************************************************/  
  210. /* 主函数调用                                                           */  
  211. /************************************************************************/  
  212. int main()  
  213. {  
  214.     int n,k;  
  215.     char a[1000],b[1000],c[1000];  
  216.     printf("%s","计算次数: ");  
  217.     scanf("%d",&n);  
  218.     while (n--)  
  219.     {  
  220.         memset(a,'/0',sizeof(a));  
  221.         memset(b,'/0',sizeof(b));  
  222.         memset(c,'/0',sizeof(c));  
  223.         printf("%s","被减数:  ");  
  224.         scanf("%s",&a);  
  225.         printf("%s","减数:    ");  
  226.         scanf("%s",&b);  
  227.         k=decimal(a,b);                           //处理小数点   
  228.         if (isBigger(a,b))                        //处理被减数与减数的大小   
  229.         {  
  230.             sub(a,b,c);                           //相减操作   
  231.             if (k!=0)  
  232.             {  
  233.                 result(c,k);                      //当是浮点数的话,对结果数组进行处理   
  234.             }  
  235.             printf("%s%s/n/n","结果为:  ",c);  
  236.         }  
  237.         else  
  238.         {  
  239.             sub(b,a,c);  
  240.             if (k!=0)  
  241.             {  
  242.                 result(c,k);  
  243.             }  
  244.             printf("%s%c%s/n/n","结果为:  ",'-',c);  
  245.         }         
  246.     }  
  247.     return 0;  
  248. }  

这篇关于高精度计算----减法运算(浮点型)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1145927

相关文章

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

uva 575 Skew Binary(位运算)

求第一个以(2^(k+1)-1)为进制的数。 数据不大,可以直接搞。 代码: #include <stdio.h>#include <string.h>const int maxn = 100 + 5;int main(){char num[maxn];while (scanf("%s", num) == 1){if (num[0] == '0')break;int len =

poj 1113 凸包+简单几何计算

题意: 给N个平面上的点,现在要在离点外L米处建城墙,使得城墙把所有点都包含进去且城墙的长度最短。 解析: 韬哥出的某次训练赛上A出的第一道计算几何,算是大水题吧。 用convexhull算法把凸包求出来,然后加加减减就A了。 计算见下图: 好久没玩画图了啊好开心。 代码: #include <iostream>#include <cstdio>#inclu

uva 1342 欧拉定理(计算几何模板)

题意: 给几个点,把这几个点用直线连起来,求这些直线把平面分成了几个。 解析: 欧拉定理: 顶点数 + 面数 - 边数= 2。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#inc

uva 11178 计算集合模板题

题意: 求三角形行三个角三等分点射线交出的内三角形坐标。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <

XTU 1237 计算几何

题面: Magic Triangle Problem Description: Huangriq is a respectful acmer in ACM team of XTU because he brought the best place in regional contest in history of XTU. Huangriq works in a big compa

音视频入门基础:WAV专题(10)——FFmpeg源码中计算WAV音频文件每个packet的pts、dts的实现

一、引言 从文章《音视频入门基础:WAV专题(6)——通过FFprobe显示WAV音频文件每个数据包的信息》中我们可以知道,通过FFprobe命令可以打印WAV音频文件每个packet(也称为数据包或多媒体包)的信息,这些信息包含该packet的pts、dts: 打印出来的“pts”实际是AVPacket结构体中的成员变量pts,是以AVStream->time_base为单位的显

计算数组的斜率,偏移,R2

模拟Excel中的R2的计算。         public bool fnCheckRear_R2(List<double[]> lRear, int iMinRear, int iMaxRear, ref double dR2)         {             bool bResult = true;             int n = 0;             dou

【Java中的位运算和逻辑运算详解及其区别】

Java中的位运算和逻辑运算详解及其区别 在 Java 编程中,位运算和逻辑运算是常见的两种操作类型。位运算用于操作整数的二进制位,而逻辑运算则是处理布尔值 (boolean) 的运算。本文将详细讲解这两种运算及其主要区别,并给出相应示例。 应用场景了解 位运算和逻辑运算的设计初衷源自计算机底层硬件和逻辑运算的需求,它们分别针对不同的处理对象和场景。以下是它们设计的初始目的简介:

GPU 计算 CMPS224 2021 学习笔记 02

并行类型 (1)任务并行 (2)数据并行 CPU & GPU CPU和GPU拥有相互独立的内存空间,需要在两者之间相互传输数据。 (1)分配GPU内存 (2)将CPU上的数据复制到GPU上 (3)在GPU上对数据进行计算操作 (4)将计算结果从GPU复制到CPU上 (5)释放GPU内存 CUDA内存管理API (1)分配内存 cudaErro