运算繁复自明理,Spring Boot轻舞间
这是后端第一次作业,为了好看,我把名字放到了博客的最后
项目说明:
(不喜勿喷,我只是在几乎完成后才知道BigInteger
的存在 o(TヘTo) )
运行程序后 访问localhost:8080/calculator?a=甲&b=乙&s=符号
其中甲,乙为一个整数或浮点数,==符号s为add
,subtract
,multiply
,division
中==的其中一个分别表示加减乘除
网页即可输出 甲 符号 乙 的值
若给入非法参数,即返回相应的错误说明
例如:
> http://localhost:8080/calculator?a=1.1&b=22.2&s=add
23.3
8.53973422267356706546355086954657449503488853576511496187960113017922861115733080757256386971047394360418507658574182427535480134567986011372683865883504670910306252214972528542462869537848950160622046
> http://localhost:8080/calculator?a=avadfsdafasdf&b=22.2&s=add
你输入的是正常数字吗?
> http://localhost:8080/calculator?a=avadfsdafasdf&b=22.2&s=adddddd
注意一下,你要输入的s应该是add,subtract,multiply,division中的其中一个
==那你可太成功了==
学习过程
1. CSDN博客
但是上面的内容鱼龙混杂,对高精度四则运算的支持程度仅停留于长整数间的加减法和长整数与普通整数间的乘除法
这远远没有达到要求(当然,我还是从中学习了一些思路和命名法的喵)
2. chatGPT
好东西,但是总是写不出正确的、符合要求的代码
我从中学习了许多字符串的处理方法,比如substring
、Integer.parseInt
然后,最后的最后,我把代码交给他让他帮我调整变量名时,他告诉我有个类叫做BigInteger
。。。。。。(TAT哭)
无所谓,手搓出BigInteger
也算是一种练习把
还有一点,他教会了我正则表达式,这真的超级好用捏!!!
代码展示与解释
MainController.java
这部分似乎看起来很==水==,没啥好解释的:
package com.example.demo.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.service.MainService;
@RestController
public class MainController
{
@Autowired
MainService sev;
@GetMapping("/calculator")
public String calculator (@RequestParam String a, @RequestParam String b, @RequestParam String s)
{
return sev.cacu( a, b, s);
}
}
==MainService.java==
这部分我想也算是==通俗易懂==吧(确信)
package com.example.demo.service;
import java.math.BigInteger;
import org.springframework.web.bind.annotation.RequestParam;
@org.springframework.stereotype.Service
public class MainService {
static int len=10000;
public String cacu( @RequestParam String a, @RequestParam String b, @RequestParam String s)
{
int fa = judgeNumber(a),fb = judgeNumber(b),sy=fa*fb; //sy存储正负号
if (sy == 0) return "你输入的是正常数字吗?"; //确认是正常数字
if (fa==-1){
a= a.substring(1, a.length());
}
if (fb==-1){
b = b.substring(1, b.length());
}
a=removeLeadingZeros(a); //去除前导零
b=removeLeadingZeros(b);
int decimalPositionOfa=findDecimalPosition(a),decimalPositionOfb=findDecimalPosition(b); //获取小数点的位置,如果没有小数点(说明是整数)就返回-1
int decimalDigitOfa,decimalDigitOfb; //储存小数点后位置,然后在去点小数点,等做完整数的四则运算后就加回去
if(decimalPositionOfa==-1)
{
decimalDigitOfa=0;
}
else
{
decimalDigitOfa=a.length()-1-decimalPositionOfa;
a=removeDecimalPoint(a, decimalPositionOfa);
}
if(decimalPositionOfb==-1)
{
decimalDigitOfb=0;
}
else
{
decimalDigitOfb=b.length()-1-decimalPositionOfb;
b=removeDecimalPoint(b, decimalPositionOfb);
}
if(s=="add"&&fa==1&&fb==-1) //倘若出现一正一负,那就直接把加号变成减号
{
s="subtract";sy=1;
}
else if(s=="add"&&fa==-1&&fb==1)
{
s="subtract";sy=-1; //sy表示整体的正负
}
else if(s=="subtract"&&fa==1&&fb==-1) //同理,把减号变成加号
{
s="add";sy=1;
}
else if(s=="subtract"&&fa==-1&&fb==1)
{
s="add";sy=-1;
}
switch(s) {
case("add"):
{
if(a.length()>len-1||b.length()>len-1) //检测位数是否超过精度
{
return "那你可太成功了";
}
if(decimalDigitOfa==0&&decimalDigitOfb==0)
{
return processSign(add(a, b),sy);
}
if(decimalDigitOfa>=decimalDigitOfb)
{
for(int i=0;i<decimalDigitOfa-decimalDigitOfb;i++)
{
b+="0";
}
return processSign(insertDecimal(add(a, b), decimalDigitOfa),sy); //计算完成后总小数点位数等于两数位数最大值
}
if(decimalDigitOfa<decimalDigitOfb)
{
for(int i=0;i<decimalDigitOfb-decimalDigitOfa;i++)
{
a+="0";
}
return processSign(insertDecimal(add(a, b), decimalDigitOfb),sy);
}
}
case("subtract"):
{
if(a.length()>len-1||b.length()>len-1) //检测位数是否超过精度
{
return "那你可太成功了";
}
if(decimalDigitOfa==0&&decimalDigitOfb==0)
{
return processSign(sub(a, b),sy);
}
if(decimalDigitOfa>=decimalDigitOfb)
{
for(int i=0;i<decimalDigitOfa-decimalDigitOfb;i++)
{
b+="0";
}
return processSign(insertDecimal(sub(a, b), decimalDigitOfa),sy); //计算完成后总小数点位数等于两数位数最大值
}
if(decimalDigitOfa<decimalDigitOfb)
{
for(int i=0;i<decimalDigitOfb-decimalDigitOfa;i++)
{
a+="0";
}
return processSign(insertDecimal(sub(a, b), decimalDigitOfb),sy);
}
}
case("multiply"):
{
if(a.length()>=len/2||b.length()>=len/2) //检测位数是否超过精度
{
return "那你可太成功了";
}
if (decimalDigitOfa==0&&decimalDigitOfb==0)
{
return processSign(mul(a, b), sy);
}
else
{
return processSign(insertDecimal(mul(a, b), decimalDigitOfb+decimalDigitOfa), sy); //计算完成后总小数点位数等于两数位数相加
}
}
case("division"):
{
if(a.length()>=len-1||b.length()>=len-1) //检测位数是否超过精度
{
return "那你可太成功了";
}
if (decimalDigitOfa==decimalDigitOfb)
{
return processSign(div(a, b), sy);
}
else if(decimalDigitOfa<decimalDigitOfb)
{
for (int i = 0; i < decimalDigitOfb-decimalDigitOfa; i++)
{
a+="0";
}
return processSign(div(a, b), sy);
}
else
{
return processSign(insertDecimal(div(a, b), decimalDigitOfa+decimalDigitOfb), sy); //计算完成后总小数点位数等于两数位数相减
}
}
default:
return ("注意一下,你要输入的s应该是add,subtract,multiply,division中的其中一个"); //检测s是否错误
}
}
//==========判断数字==========
public static int judgeNumber(String str)
{
if (str.matches("\\d+(\\.\\d+)?")) return 1; // 匹配数字
else if (str.matches("^[-]\\d+(\\.\\d+)?")) return -1; // 判断是否为负数
else return 0;
}
//==========去除前导零=========
public static String removeLeadingZeros(String numString)
{
int i = 0;
while (i < numString.length() && numString.charAt(i) == '0')
{
i++;
}
return i == numString.length() ? "0" : numString.substring(i);
}
//==========找到小数点的位置==========
public static int findDecimalPosition(String number)
{
int position = -1;
for (int i = 0; i < number.length(); i++)
{
if (number.charAt(i) == '.')
{
position = i;
break;
}
}
return position;
}
//==========去掉小数点==========
public static String removeDecimalPoint(String number, int decimalPosition)
{
if (decimalPosition == -1)
{
return number;
}
else
{
return number.substring(0, decimalPosition) + number.substring(decimalPosition + 1);
}
}
//==========插入小数点==========
public static String insertDecimal(String number, int n)
{
while (number.length()<=n)
{
number="0"+number;
}
int length = number.length();
int index = length - n;
return number.substring(0, index) + "." + number.substring(index);
}
//==========处理正负号==========
public static String processSign(String num, int sy)
{
if (sy == 1)
{
return num;
}
else if (sy == -1 && num.startsWith("-"))
{
return num.substring(1);
}
else
{
return "-" + num;
}
}
//==========将一个整数倒序放入数组==========
static void write(String str,int[] arr)
{
int i=str.length()-1,j=0;
while (i>=0) {
arr[j]=str.charAt(i)-'0';
i--;j++;
}
}
//==========高精度加法==========
static String add(String A,String B)
{
int[] a=new int[len]; //存放A
int[] b=new int[len]; //存放B
int[] c=new int[len]; //结果集
write(A, a);
write(B, b);
int jin=0;//进位
for (int i = 0; i <len ; i++)
{
int he=a[i]+b[i]+jin;
c[i]=he%10;
jin=he/10;
}
int index=0;
for (int i = len-1; i >=0 ; i--)
{
if (c[i]!=0){
index=i;
break;
}
}
String C="";
for (int i = index; i >=0 ; i--)
{
C+=c[i];
}
return C;
}
//==========半高精度加法==========
static int[] arrAdd(int[] a,int[] b,int wei)
{
int[] c=new int[len]; //结果集
int jin=0;//进位
int he;
for (int i = 0; i <len ; i++)
{
if (i<wei)
{
c[i]=a[i];
}
else
{
he=a[i]+b[i-wei]+jin;
c[i]=he%10;
jin=he/10;
}
}
return c;
}
//==========高精度减法==========
static String sub(String A, String B)
{
if (A.equals(B))
{
return "0";
}
int flag=0; //是否要加负号
int lena=A.length();
int lenb=B.length();
if (lena<lenb)
{ //粗略判断正负
String temp=A;
A=B;
B=temp;
flag=1;
}
if (lena==lenb)
{ //更精细地判断正负
int count=0;
while (count<lena)
{
int aa=Integer.parseInt(A.charAt(count)+"");
int bb=Integer.parseInt(B.charAt(count)+"");
if (aa<bb)
{
flag=1;
String temp=A;
A=B;
B=temp;
break;
}
else if(aa>bb)
{
break;
}
count++;
}
}
int[] a = new int[len]; //存放A
int[] b = new int[len]; //存放B
int[] c = new int[len]; //结果集
write(A, a);
write(B, b);
for (int i = 0; i < len-1; i++)
{
int cha = 0;
if (a[i] < b[i])
{
cha = a[i] - b[i] + 10;
a[i + 1]--; //借位处要减去1
}
else
{
cha = a[i] - b[i];
}
c[i] = cha;
}
int index = 0;
for (int i = len - 1; i >= 0; i--)
{
if (c[i] != 0)
{
index = i;
break;
}
}
String C = "";
for (int i = index; i >= 0; i--)
{
C += c[i];
}
if (flag==1)
{
return "-"+C;
}
return C;
}
//==========判断两数大小==========
static int subSub(String A, String B)
{
if (A.equals(B))
{
return 0;
}
int flag=0; //是否要加负号
int lena=A.length();
int lenb=B.length();
if (lena<lenb)
{ //粗略判断正负
flag=1;
}
if (lena==lenb){ //更精细地判断正负
int count=0;
while (count<lena)
{
int aa=Integer.parseInt(A.charAt(count)+"");
int bb=Integer.parseInt(B.charAt(count)+"");
if (aa<bb)
{
flag=1;
break;
}
else if(aa>bb)
{
break;
}
count++;
}
}
return flag;
}
//==========半高精度乘法==========
static int[] subMul(int[] a,int b)
{
int[] c=new int[len]; //结果集
int jin=0; //进位存储器
for (int i = 0; i <len/2 ; i++)
{
int ji=a[i]*b+jin;
c[i]=ji%10;
jin=ji/10;
}
return c;
}
//==========高精度乘法==========
static String mul(String A,String B)
{
int[] a=new int[len/2]; //存放A
int[] b=new int[len/2]; //存放B
int[] c=new int[len]; //结果集
write(A, a);
write(B, b);
for (int i = 0; i < len/2; i++)
{
c=arrAdd(c, subMul(a, b[i]), i);
}
int index=0;
for (int i = len-1; i >=0 ; i--) //利用竖式方法,把多位数相乘转化为一个单个整数乘以多位数,然后再相加
{
if (c[i]!=0)
{
index=i;
break;
}
}
String C="";
for (int i = index; i >=0 ; i--)
{
C+=c[i];
}
return C;
}
//==========高精度除法==========
public static String div(String a, String b)
{
BigInteger dividend = new BigInteger(a);
BigInteger divisor = new BigInteger(b);
BigInteger result = dividend.divide(divisor);
return result.toString();
}
/*
//==========高精度除法==========
static String div(String A,String B){
int[] b=new int[len];
int[] c=new int[len]; //结果集
String C="";
write(B, b);
if (A.length()<B.length()) //简单判断大小关系
{
return "0";
}
for(int i=B.length()-1;i<A.length();i++){ //传统竖式原理
for(int j=9;j>=0;i++){
int[] bj=subMul(b, j); //计算b*j并把它转成去掉前导零的字符串
int index=0;
for (int x = len-1; x >=0 ; x--)
{
if (bj[x]!=0)
{
index=x;
break;
}
}
String BJ="";
for (int x = index; x >=0 ; x--)
{
BJ+=bj[i];
}
if(subSub(A.substring(0,i), BJ)==0) //得到该位数字,并得出余数
{
C+=j+'0';
String temp=div(A, BJ);
temp+=A.substring(temp.length(),A.length());
A=temp;
break;
}
}
}
return C;
}
*/
}
其中最后一部分是我出bug的高精度除法,改正方法很简单,但是会大大增长代码量,为了各位的阅读方便,我就直接用外星方法解决了
里面的注释加得很具体了,在此就不一一介绍了
作者
林星宇