用C语言写一个计算器

article/2025/11/7 18:55:51

用C语言写一个计算器,除了四则混合运算之外,还支持三角函数和绝对值等函数。

PS E:\Code\PL\calc> .\a.exe     
abs(3*5-4^2)
abs(3*5-4^2)=1.000000
25-7+6*(4-5)
25-7+6*(4-5)=12.000000

文章目录

    • 1. 加减法运算
    • 2. 加法和乘法
    • 3. 四则混合运算
    • 4. 浮点型计算器程序
    • 5. 加入三角函数

在计算器中,至少包含两类变量,即数字和运算符。例如,如果希望实现 a + b × ( c − d ) a+b\times (c-d) a+b×(cd)这样一个简单的功能,要求编译器可以识别出 + , × , − , ( , ) +,\times,-,(,) +,×,,(,)这五个符号,并理清彼此的计算顺序,最后生成一棵语法树,然后实现输出。

1. 加减法运算

万事开头难,所以我们选择一个简单到无脑的开头。首先,我们考虑实现 a + b a+b a+b这样简单的两数运算,即如下所示,十分简单且无脑。

void douCalc(){while (1){double i, j, s;char k;scanf("%lf%c%lf", &i, &k, &j);switch (k){case '+':s = i+j;break;case '-':s = i-j;break;case '*':s = i*j;break;case '/':s = i/j;break;default:break;}printf("%lf\n", s);}
}

然后,我们考虑,如何实现一个连加器,旨在解决 a + b + c + . . . a+b+c+... a+b+c+...的计算问题。这里虽然不涉及到运算次序,但仍旧需要处理多个不确定个数的变量,所以我们不再可以直接用类似scanf("%lf%c%lf", &i, &k, &j);的方案来实现数据的输入,而必须建立一个链表来存储变量。

C语言输入输出

在C语言中,可以通过至少三种方式来读取键盘输入的值:

  • scanf():和 printf() 类似,scanf() 可以输入多种类型的数据。
  • getchar()getche()getch():这三个函数都用于输入单个字符。
  • gets():获取一行数据,并作为字符串处理。

其中,scanf是格式化扫描的意思,可以通过格式控制符对输入字符进行格式化,并赋值给相关变量。

格式控制符说明
%c读取单一字符
%s读取一个字符串(以空白符为结束)
%f、%lf读取十进制形式小数,赋值给float、double 类型
%e、%le读取指数形式小数,赋值给 float、double 类型
%g、%lg读取十进制或指数形式的小数,
并分别赋值给 float、double 类型
  • 整数格式化
    shortintlong
    十进制%hd%d%ld
    八进制%ho%o%lo
    十六进制%hx%x%lx
    无符号%hu%u%lu

getchar()等价于scanf("%c", c),相对来说更加简单。getchegetch是Windows独有的函数,在头文件conio.h中故不赘述。

getsscanf(%s,s)的区别在于,后者在使用的过程中会把空格当作终止符,而前者不会。

所以,我们在实现连加的过程中,会使用gets作为交互方法。

由于我们实现的是一个连加器,所以输入字符中只包含数字和加号,那么接下来,我们需要遍历输入字符,通过加号来将数字分开。我们可以很方便地写下一个简单而丑陋的小程序。

void adds(){char str[100];char numStr[20];int num[20];       int val;int i,j,k;while (1){gets(str);i = 0;j = 0;k = 0;while (str[i]!='\0'){if (str[i]=='+'){num[k] = atoi(numStr);k++;j = 0;}else{numStr[j] = str[i];j++;}i++;}num[k]=atoi(numStr);val = 0;for (int i = 0; i < k+1; i++){val += num[i];}printf("%d\n",val);}
}int main(){adds();return 0;
}

由于加减法具有相同的运算优先级,在实现上不过是为后续的数字加上一个负号而已,故可十分方便地在原有程序上修改。

此外,adds代码乍看上去没什么问题,但str的值在更新之前,并不会自动清零,由此带来的bug需要创建一个字符串清零的函数。修改之后的代码如下

#include <stdio.h>
#include <stdio.h>
#include <string.h>
#include <math.h>void strClear(char *str,int n){for (int i = 0; i < n; i++){str[i]=NULL;}
}void adds(){char str[100];char numStr[20];int num[20];       int val;int i,j,k;while (1){gets(str);i = 0;j = 0;k = 0;while (str[i]!='\0'){if (str[i]=='+'){num[k] = atoi(numStr);strClear(numStr,20);k++;j = 0;}else if (str[i]=='-'){num[k] = atoi(numStr);strClear(numStr,20);k++;numStr[0] = str[i];j = 1;}else{numStr[j] = str[i];j++;}i++;}num[k]=atoi(numStr);strClear(numStr,20);val = 0;for (int i = 0; i < k+1; i++){val += num[i];}printf("%d\n",val);}
}int main(){adds();return 0;
}

精简一下

#include <stdio.h>
#include <stdio.h>
#include <string.h>
#include <math.h>void strClear(char *str,int n){for (int i = 0; i < n; i++){str[i]='\0';}
}
void adds1(){char str[100];char numStr[20];int i,j,val;while (1){gets(str);i = 0;j = 0;val = 0;while (str[i]!='\0'){if ((str[i]=='+')||(str[i]=='-')){val += atoi(numStr);strClear(numStr,20);j = 0;if (str[i]=='-')numStr[j++]=str[i];}elsenumStr[j++] = str[i];i++;}val += atoi(numStr);strClear(numStr,20);printf("%d\n",val);}
}int main(){adds1();return 0;
}

2. 加法和乘法

若希望加入乘法和除法,那么修改代码的过程就相对复杂了,因为乘除法在运算过程中,具有比加减法更高的优先级。那么我们就无法通过一个简单的数组来存储变量,而必须建立一种树形的结构。

例如,对于 a + b × c − d × e / f a+b\times c-d\times e/f a+b×cd×e/f,可写成如下形式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ruufs0c0-1608717185925)(img/calc1.png)]
在这里插入图片描述

我们可以看到,这是一个二叉树,每个叶节点都是数字,而两个叶节点的父节点则为运算符。我们通过这个运算符来计算其子节点后,删除它的两个子节点,同时运算符所对应的节点退化为叶节点,同时其类型也变为数字。

对于上图而言,先计算 e / f e/f e/f,然后计算 b × c b\times c b×c d × e / f d\times e/f d×e/f,再计算 b × c − d × e / f b\times c-d\times e/f b×cd×e/f,最后计算最上面的加法。

对于树来说,我们的遍历往往从根节点开始,所以其计算规则如下:

  1. 如果当前节点的子节点为叶节点,则计算当前节点,并删除该节点的叶节点,然后考虑其父节点。
  2. 如果当前节点的某个子节点不是叶节点,则处理该子节点,直到该子节点成为叶节点为止。
  3. 如果当前节点为根节点,且为叶节点,则输出计算结果。

对于节点来说,除了父子节点外,则至少有两个属性:

  1. isLeaf:用于叶节点判定。在这里,叶节点不仅有结构上的意义,更有着明确的语义:它只能是数字。
  2. value:对于叶节点而言,这个值为数字,否则的话,这个值为运算符号及其所对应的计算规则。
# define MAXLEN 100
typedef struct NODE{struct NODE *father;struct NODE *Left;struct NODE *Right;char value[MAXLEN];int isLeaf;
}Node;

生成计算树

由于我们规定了两个运算层级,所以再遍历字符串以生成计算树的过程中,需要两次循环,即首先生成加减法的计算树,然后再生成乘除法的计算树。

生成计算树的过程可以简化为字符串不断拆分的过程,为了简化思维,我们只考虑两个符号+*,这两个符号分别代表两种计算层级。

由此可得到如下代码。对于

# define TRUE 1
# define FALSE 0
void newNode(Node *root, Node *father){root -> father = father;root ->Left = NULL;root -> Right = NULL;root -> isLeaf = FALSE;
}//root 为根节点,str为字符串
void initCalcTree(Node *root, char flag){for (int i = 0; i < MAXLEN; i++){if (root->value[i]==flag){Node *Left = (Node *)malloc(sizeof(Node));Node *Right = (Node *)malloc(sizeof(Node));newNode(Left,root);newNode(Right,root);for (int j = 0; j < i; j++)Left -> value[j] = root->value[j];Left->value[i] = '\0';i++;for (int j = i; j < MAXLEN; j++)Right -> value[j-i] = root->value[j];root->Left = Left;root->Right = Right;strClear(root->value,MAXLEN);root->value[0] = flag;root->value[1] = '\n';initCalcTree(Left,'*');if (flag=='+')initCalcTree(Right,'+');elseinitCalcTree(Right,'*');break;}else{if (root->value[i]=='\0'){if(flag =='+')initCalcTree(root,'*');elseroot -> isLeaf = TRUE;break;}elsecontinue;}}
}

测试一下

void printNode(Node *root,int start){printf("the %dth node is %s\n", start, root->value);if (root->isLeaf==FALSE){printNode(root->Left, start + 1);printNode(root->Right, start + 1);}
}int main(){Node *root = (Node *)malloc(sizeof(Node));char *str = "1+21*3+3*4*5+6";strcpy(root->value,str);initCalcTree(root,'+');printNode(root,0);return 0;
}

得到结果为

the 0th node is +the 1th node is 1
the 1th node is +the 2th node is *the 3th node is 21
the 3th node is 3
the 2th node is +the 3th node is *the 4th node is 3
the 4th node is *the 5th node is 4
the 5th node is 5
the 3th node is 6

然后,我们再对计算树进行计算。当被计算的量为叶节点时,则返回该节点的值;如果该节点的两个节点都是叶节点,则返回该节点处的运算符对这两个子节点的计算值;如果该节点的两个节点都不是叶节点,那么对这两个子节点进行计算。

int calcNode(Node *root){if(root->isLeaf == TRUE)return atoi(root->value);else if (root->Left->isLeaf * root->Right->isLeaf == TRUE){if(root->value[0] == '+')return atoi(root->Left->value)+atoi(root->Right->value);elseatoi(root->Left->value)*atoi(root->Right->value);}else{if (root->value[0] == '+')return calcNode(root->Left)+calcNode(root->Right);elsereturn calcNode(root->Left)*calcNode(root->Right);}
}int main(){Node *root = (Node *)malloc(sizeof(Node));char str[MAXLEN];while (1){gets(str);strcpy(root->value,str);initCalcTree(root,'+');printf("%s=%d\n",str,calcNode(root));}return 0;    
}

结果为

PS E:\Code\PL\calc> .\a.exe
1+2+3*4+15*2
1+2+3*4+15*2=45
2*5+3*6*12
2*5+3*6*12=226

3. 四则混合运算

如果考虑加减乘除,那么意味着一个运算级别下有多种运算符,所以我们需要通过一个函数来返回运算符的运算次序。

int getOrder(char ch){int result;switch (ch){case '+':case '-':return 0;case '*':case '/':return 1;default:return 2;}
}

然后,基于此,修改计算树的生成与计算代码。

int douCalc(char c,int a, int b){switch (c){case '+':return a+b;case '-':return a-b;case '*':return a*b;case '/':return a/b;}
}void newNode(Node *root, Node *father){root -> father = father;root ->Left = NULL;root -> Right = NULL;root -> isLeaf = TRUE;father -> isLeaf = FALSE;
}//root 为根节点,str为字符串,N为字符串长度
void initCalcTree(Node *root, int order){for (int i = 0; i < MAXLEN; i++){if (getOrder(root->value[i])==order){Node *Left = (Node *)malloc(sizeof(Node));Node *Right = (Node *)malloc(sizeof(Node));newNode(Left,root);newNode(Right,root);for (int j = 0; j < i; j++)Left -> value[j] = root->value[j];Left->value[i] = '\0';i++;for (int j = i; j < MAXLEN; j++)Right -> value[j-i] = root->value[j];root->Left = Left;root->Right = Right;root->value[0] = root->value[i-1];root->value[1] = '\0';initCalcTree(Right,order);if (order<1)initCalcTree(Left,order+1);break;}else if((i==0)&&(order<2))initCalcTree(root,order+1);}
}
int calcNode(Node *root){if(root->isLeaf == TRUE)return atoi(root->value);else if (root->Left->isLeaf * root->Right->isLeaf == TRUE)return douCalc(root->value[0],atoi(root->Left->value),atoi(root->Right->value));elsereturn douCalc(root->value[0],calcNode(root->Left),calcNode(root->Right));
}
int main(){Node *root = (Node *)malloc(sizeof(Node));char str[MAXLEN];while (1){gets(str);strcpy(root->value,str);initCalcTree(root,0);printf("%s=%d\n",str,calcNode(root));}return 0;    
}

至此,我们得到了一个计算器的“骨架”,为运算符设定相应的运算次序,相当于提供一种生成方法,这种方法可以直接扩展到更多的运算符上。

同时,上述代码中也出现了两个问题:

  1. 我们默认计算的是整型数据,所以无法处理浮点型运算
  2. 减法和除法虽然在名义上与加法、乘法处于相同的运算次序中,但我们的生成树中默认的是从右向左计算。对于 a + b − c + d a+b-c+d a+bc+d这样的表达式,会计算成 a + b − ( c + d ) a+b-(c+d) a+b(c+d)的形式,这是错误的。

针对这种运算结构的一个优势和两个问题,我们继续改进这个计算器程序。

4. 浮点型计算器程序

首先,我们将所有函数与变量均改为double类型;然后我们更改输入字符串的遍历方式,从后向前进行遍历。

我们再加入乘方运算符^,给它一个更高的运算层级

int getOrder(char ch){int result;switch (ch){case '+':case '-':return 0;case '*':case '/':return 1;case '^':return 2;case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':return 3;default:return 4;}
}double douCalc(char c,double a, double b){switch (c){case '+': return a+b;case '-': return a-b;case '*': return a*b;case '/': return a/b;case '^': return pow(a,b);}
}

至此,我们写出了一个可以计算+-x÷^的程序。但我们还不能处理表达式中可能出现的括号。

括号在表达式中成对出现,故不同于常规运算符,需要在表达式的两端进行遍历;另外,括号不具备运算功能,只有规定运算次序的作用,对于括号运算符只有一个子节点。所以,只需更改initCalcTree的代码。

由于我们将算法改为从右向左遍历,所以如果最后一个字符不是),则不必考虑括号的影响。当最后一个字符为)时,如果第0个字符为(,则将括号里面的内容提取出来,针对此时的节点重新进行遍历即可。如果自左向右遍历的过程出现第一个(的位置是posLeft,则后面关于运算符的遍历从posLeft开始。

//root 为根节点,str为字符串,N为字符串长度
void initCalcTree(Node *root, int order){int lenStr = strlen(root->value);int posLeft = lenStr;//如果末尾为')',则查找其对应的左括号的位置if(root->value[lenStr-1]==')'){for (int i = 0; i < lenStr; i++)if(root->value[i]=='(')posLeft = i;if (posLeft == 0){for (int i = 1; i < lenStr-1; i++)root->value[i-1] = root->value[i];root->value[lenStr-2]='\0';initCalcTree(root,0);}}//如果左括号的位置不为0,则for (int i = posLeft; i >= 0; i--){if (getOrder(root->value[i])==order){Node *Left = (Node *)malloc(sizeof(Node));Node *Right = (Node *)malloc(sizeof(Node));newNode(Left,root);newNode(Right,root);for (int j = 0; j < i; j++)Left -> value[j] = root->value[j];Left->value[i] = '\0';i++;for (int j = i; j < MAXLEN; j++)Right -> value[j-i] = root->value[j];root->Left = Left;root->Right = Right;root->value[0] = root->value[i-1];root->value[1] = '\0';  //字符串末尾标记initCalcTree(Left,order);if ((order<2)||(posLeft!=lenStr))initCalcTree(Right,order+1);break;}else if((i==0)&&(order<2))initCalcTree(root,order+1);}
}

至此,我们就写好了一个简陋的可以进行四则混合运算的计算器程序

PS E:\Code\PL\calc> .\a.exe     
1+2*(3-4)+5
1+2*(3-4)+5=4.000000
2^(3+1)
2^(3+1)=16.000000

5. 加入三角函数

现在我们需要考虑加入三角函数,其难点在于函数的识别。

我们规定,单变量函数通过括号的方式导入实参,也就是说,只要表达式中不出现括号,那么就不必考虑括号的问题。换句话说,判定函数,必然在判定括号之后。

考虑到我们定义的getOrder函数中,除了我们所规定的符号和数字之外,其他符号和字母的默认返回值为4。所以需要在判定括号之后,继续进行函数的判断。

故而需要更改括号判定的代码

/*...*/if(root->value[lenStr-1]==')'){for (int i = 0; i < lenStr; i++)if(root->value[i]=='(')posLeft = i;if (posLeft == 0){for (int i = 1; i < lenStr-1; i++)root->value[i-1] = root->value[i];root->value[lenStr-2]='\0';initCalcTree(root,0);}else{            int lenFunc=0;posLeft--;while ((getOrder(root->value[posLeft])==4)&&(posLeft>0)){posLeft--;lenFunc++;}//当posLeft变为0时,说明此节点为无法分割的函数if (posLeft==0){root->value[lenFunc+1]='\0';Node *Left = (Node *)malloc(sizeof(Node));root->Left = Left;newNode(Left,root);for (int i = lenFunc+2; i < lenStr-1; i++){Left->value[i-lenFunc-2]=root->value[i];}Left->value[lenStr-lenFunc-2]='\0';initCalcTree(Left,0);   //对左子节点进行生成return 0;}}}
/*...*/

接下来,我们需要修改calcNode函数,即在计算运算符之前,添加一个函数处理程序。其中,strcmp为字符串比对函数,当两个字符串相等时,返回0。

double doFunc(char *str,double val){if (strcmp(str,"sin")==0)return sin(val);else if (strcmp(str,"cos")==0)return cos(val);else if (strcmp(str,"tan")==0)return tan(val);else if (strcmp(str,"arcsin")==0)return asin(val);else if (strcmp(str,"arccos")==0)return acos(val);else if (strcmp(str,"arctan")==0)return atan(val);else if (strcmp(str,"sqrt")==0)return sqrt(val);else if (strcmp(str,"abs")==0)return abs(val);    
}double calcNode(Node *root){if(getOrder(root->value[0])==4)return doFunc(root->value,calcNode(root->Left));if(root->isLeaf == TRUE)return atof(root->value);else if (root->Left->isLeaf * root->Right->isLeaf == TRUE)return douCalc(root->value[0],atof(root->Left->value),atof(root->Right->value));elsereturn douCalc(root->value[0],calcNode(root->Left),calcNode(root->Right));
}

至此,我们已经用C语言实现了一个简陋而且有不少bug的计算器,比如并未设置除零报警之类的功能,但一般的操作是没有问题的。

abs(3*5-4^2)
abs(3*5-4^2)=1.000000
25-7+6*(4-5)
25-7+6*(4-5)=12.000000

http://chatgpt.dhexx.cn/article/MQ45SNrt.shtml

相关文章

使用C语言构造一个简单计算器

本节我们用小学生知识来制作一个简单的计算器&#xff0c;可以运算加&#xff0c;减&#xff0c;乘&#xff0c;除&#xff0c;以及余数的运算。 在这节代码中用到switch语句&#xff0c;因为要输入运算符&#xff0c;所以注意%c的对应 接下来上代码&#xff1a; #include &…

用c语言编写一个简易计算器

更高级的计算器移步http://t.csdn.cn/E2rVG 文章目录 前言一、原理是什么&#xff1f;二、使用步骤 1.代码总结 前言 利用C语言编写一个能够进行简单加减乘除的计算器 一、原理是什么&#xff1f; 利用C语言自带算法&#xff0c;进行简单的逻辑运算 二、使用步骤 1.代码 …

【C语言】计算器

&#x1f680;write in front&#x1f680; &#x1f50e;大家好&#xff0c;我是謓泽&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流&#x1f50e; &#x1f3c5;2021年度博客之星物联网与嵌入式开发TOP5&#xff5e;2…

通信行业研究宝典

文章大纲 哑铃型布局&#xff0c;从供应链、产业链到场景链端-智能硬件&#xff1a;万亿大市场&#xff0c;小米重兵布局管-物联网核心基础设施&#xff0c;小米重点布局芯片、模组、小基站云-应用服务布局&#xff1a;布局向家、车、天场景延伸&#xff0c;文娱迎来新增长 通信…

HTTP RPC Dubbo hsf Spring-cloud 图解比较

前言 HSF是一个分布式的远程服务调用框架&#xff0c;其实我更喜欢把分布式几个字去掉&#xff0c;因为HSF本身并不是一个单独的服务&#xff08;指一个进程&#xff09;&#xff0c;他是附属在你的应用里的一个组件&#xff0c;一个RPC组件(远程过程调用——Remote Procedure…

第五章:产品管理

本章索引&#xff1a; [第五章&#xff1a;产品管理(1) – 产品管理介绍] [第五章&#xff1a;产品管理(2) – 需求管理方法] [第五章&#xff1a;产品管理(3) – 目标管理 ] [第五章&#xff1a;产品管理(4) – 团队沟通] [第五章&#xff1a;产品管理(5) – 团队协同] …

5G时代,产业互联网新生态正在加速形成。

转自:微点阅读(www.weidianyuedu.com)微点阅读 - 范文大全 - 免费学习网站 导 读 回顾整个移动通信发展史,有人说2G时代发短信是最时髦的通信方式,3G时代微信兴起,4G时代手机把衣食住行都“管起来”。 到了5G时代,已经突破传统通信技术人与人之间点对点的通信模式,大…

[已授权] 互联网定位技术小谈

​ 诚邀阿里云先知社区邀请&#xff0c;不胜感激&#xff01;今日小编在此为大家介绍一下互联网中所应用的定位技术。互联网的发展日新月异&#xff0c;技术迭代很快&#xff0c;各行各业的智慧在互联网这片蓝天下碰撞结晶&#xff0c;造福大众。今天要讲述的集中定位方式&…

5G承载网,到底有哪些关键技术?

戳蓝字“CSDN云计算”关注我们哦&#xff01; 作者 | 小枣君 来源 | 鲜枣课堂 之前小枣君给大家介绍了5G承载网的基本知识&#xff08;链接&#xff1a;5G承载网到底有什么不同&#xff1f;&#xff09;。今天&#xff0c;我们再来看看5G承载网中的常见关键技术。 首先&#x…

IDC报告称中国成为全球第二大公有云 IaaS 市场;腾讯牵手宝马在华设云计算中心;华为5G折叠屏手机通过入网许可:8月上市……...

关注并标星星CSDN云计算 极客头条&#xff1a;速递、最新、绝对有料。这里有企业新动、这里有业界要闻&#xff0c;打起十二分精神&#xff0c;紧跟fashion你可以的&#xff01; 每周三次&#xff0c;打卡即read 更快、更全了解泛云圈精彩news go go go 海盗船已推出第一款32G…

中台架构的未来在哪—开放式架构

春节前应“技术琐话”之约&#xff0c;试图写一篇讨论架构方法论的文章&#xff0c;然而动笔之后&#xff0c;才发现&#xff0c;自己似乎陷入了Frederick P. Brooks先生在《设计原本》一书中指出的问题&#xff1a;“设计中最困难的部分在于决定要设计什么”。 2020年1月18日…

大多数人不知道的企业数据分析能力金字塔,你处在哪一级?

写这篇文章来源于两个故事&#xff1a; 故事一&#xff1a;一位在互联网行业做数据库架构多年的朋友一起吃饭&#xff0c;问起我现在在做什么&#xff0c;我说自己在做医疗方面的数据分析&#xff0c;朋友笑&#xff0c;说&#xff1a;你有很多资源啊&#xff0c;只要你能拿到…

美团 大规模商品知识图谱的构建与应用

作者 | 曹雪智博士 美团 技术专家 来源 | DataFunTalk 在互联网新零售的大背景下&#xff0c;商品知识图谱作为新零售行业数字化的基石&#xff0c;提供了对于商品相关内容的立体化、智能化、常识化的理解&#xff0c;对上层业务的落地起到了至关重要的作用。 相比于美团大脑中…

我逃到国企了

文章内容整理自公众号国企程序锅 文章目录 入职国企心得体会 一、入职前二、入职后三、工作开发内容四、钱总结&#xff1a;北京户口相关问题 一、北京户口咋获得&#xff1f;二、北京户口有啥用&#xff1f;三、高薪无户口VS低薪有户口&#xff1f;总结&#xff1a;秋招找国企…

小程序,是腾讯云的杀手锏?

“【报告下载】后台回复关键词“数据智能”可免费下载数据猿最新发布的完整高清版《2021中国数据智能产业发展报告》 大数据产业创新服务媒体 ——聚焦数据 改变商业 在中国云计算市场&#xff0c;腾讯云长期坐着第二把交椅。但是&#xff0c;这两年华为云发展太快&#xff0c…

[nlp] 小傻学数据预处理

[nlp] 小傻学数据预处理 1. 分词1.1 分词方法1.1.1 基于规格&#xff08;词典、词库&#xff09;1.1.2 基于知识理解1.1.3 基于(词频)统计 1.2 分词工具1.3 jieba分词原理1.3.1 前缀词典1.3.2 有向无环图生成1.3.3 计算概率最大路径 2 文本纠错2.1 why&#xff1f;2.1.12.2 英文…

基于STM32的酒驾监控系统设计与实现(OneNet云平台)

一、设计需求 1.1 设计需求总结 随着社会的发展和人们生活水平的提高,汽车已经成为人们出行的主要代步工具,与此同时,酒后驾车所引发的事故越来越多,对人们的生命安全带来了威胁。为了控制酒后驾车,本文设计了一款能够安装在车辆驾驶室内的酒后驾车监测系统。 基于STM3…

互联网时代“陨落”,国家发布元宇宙战略的信号对失业和担心失业的我们带来了什么启迪?

互联网这头“猪 ”真的掉下来了 流量红利已经一去不复返了&#xff01;3年前业界其实已经发出各种密集信号&#xff0c;在当时无论是BAT还是一些经济学家在3年前都已经预测过&#xff0c;互联网的流量模式已经衰竭&#xff0c;并且它将一去不复返。 曾经处于互联网大潮的我们…

架构之争:数用一体VS数用分离,谁才是永远滴神

文章目录 &#x1f34f;1 数用分离为什么不适合现代技术应用模式了&#xff1f;&#x1f34e;1.1 信息化前期阶段数用分离的价值&#x1f350;1.2 数字化效率加快的背景下&#xff0c;数用一体或是新模式&#x1f34a;1.3 数用分离与数用一体对比模式 &#x1f34c;2 smardaten…

互联网定位技术小谈

小编刚刚入驻了阿里云先知社区&#xff0c;整理发文&#xff1a; https://xianzhi.aliyun.com/forum/read/775.html 欢迎点评&#xff01;首发保护的原因&#xff0c;本次发文将延迟一周更新到这里。这篇文章不在openGPS.cn站点首发 诚邀阿里云先知社区邀请&#xff0c;不胜感…