C语言 —— 浮点类型详解及 IEEE754 规定

【C语言趣味教程】(3) 浮点类型:单精度浮点数 | 双精度浮点型 | IEEE754 标准

   🔗 《C语言趣味教程》👈 猛戳订阅!!!

—— 热门专栏《维生素C语言》的重制版 ——

  • 💭 写在前面:这是一套 C 语言趣味教学专栏,目前正在火热连载中,欢迎猛戳订阅!本专栏保证篇篇精品,继续保持本人一贯的幽默式写作风格,当然,在有趣的同时也同样会保证文章的质量,旨在能够产出 "有趣的干货" !本系列教程不管是零基础还是有基础的读者都可以阅读,可以先看看目录! 标题前带星号 (*) 的部分不建议初学者阅读,因为内容难免会超出当前章节的知识点,面向的是对 C 语言有一定基础或已经学过一遍的读者,初学者可自行选择跳过带星号的标题内容,等到后期再回过头来学习。值得一提的是,本专栏 强烈建议使用网页端阅读! 享受极度舒适的排版!你也可以展开目录,看看有没有你感兴趣的部分!希望需要学 C 语言的朋友可以耐下心来读一读。最后,可以订阅一下专栏防止找不到。

" 有趣的写作风格,还有特制的表情包,而且还干货满满!太下饭了!"

—— 沃兹基硕德

📜 本章目录:

Ⅰ. 浮点类型(Float Point)

0x00 引入:什么是浮点数?

0x01 单精度浮点型:float

0x02 双精度浮点型:double

0x03 浮点数 “精度丢失” 问题

0x04 浮点数类型的表达方式

* 0x05 复数浮点型:complex_float / complex double

Ⅱ. 二进制浮点数算术标准(IEEE754)

0x00 引入:浮点数的存储

0x01 IEEE754 规定

0x02 阅读:雷神之锤 III 源码中的 "平方根倒数速算法"

Ⅲ. 浮点数类型的表达方式(Float Expression)

0x00 引入:浮点数类型的表示

0x01 十进制小数型:x.

0x02 指数型:xEn


Ⅰ. 浮点类型(Float Point)

0x00 引入:什么是浮点数?

在讲解浮点类型前,我们不妨先先来了解一下什么是浮点数,浮点 (float point):

顾名思义就是 "一个漂浮的点",其英文 float 也是这个含义(浮动, 漂浮之意)。

因此,浮点数指的是一个数的小数点的位置不是固定的,而是可以浮动的。

浮点数在数学中的定义:浮点数是属于有理数中某个特定子集的数的数字表示。

C 语言的浮点型是用来存放小数类型的数字的,可分为 单精度 和 双精度,我们稍后会作讲解。

" 程序员不得不知道的标准,IEEE754 标准! "

电气电子工程师学会 (IEEE) 颁布过一个浮点数标准,全称 IEEE 二进制浮点算数标准。

简称 IEEE754,是被绝大部分 CPU 和浮点运算器所采用的一套浮点数标准。

0x01 单精度浮点型:float

我们可以用 float 类型来表示小数,称为 单精度浮点型 (single floating-point) 。

float 变量名 = 值;

float 的精度为 6~7 位小数,float 类型占 4 个字节。

我们来使用 float 定义一些变量:

float height = 170.00;
float weight = 50.5;
float pi = 3.14;
float zero = 0.0;

我们可以使用 float 专属的格式化字符 %f 来打印浮点类型变量。

💬 代码演示:打印浮点数

#include <stdio.h>

int main(void)
{
    float pi = 3.14;
    printf("%f", pi);

    return 0;
}

🚩 运行结果:3.140000

此时我们发现结果为 3.140000,而不是 3.14,因为把精度全部都打出来了。

我们可以用 %.Xf 来控制保留小数点位数,其中 X 是几就保留几位。

这里我们想保留两位,所以 %.2f 即可:

#include <stdio.h>

int main(void)
{
    float pi = 3.14;
    printf("%.2f", pi);

    return 0;
}

🚩 运行结果:3.14

0x02 双精度浮点型:double

刚才介绍了单精度浮点型 float,表示的数需要的精度较低,就可以用 float 来定义。

如果表示的数要求的精度较高,我们就可以使用 double 类型来定义。

double双精度浮点型 (double floating-point),double 类型的精度比 float 类型要高得多。

double 变量名 = 值;

double 类型的精度为 15~16 位小数,相应的占的字节数也更多,double 类型占 8 个字节。

我们可以使用 double 专属的格式化字符 %lf 来打印 double 类型的变量:

#include <stdio.h>

int main(void)
{
    double pi = 3.141592;
    printf("%lf\n", pi);

    return 0;
}

🚩 运行结果:3.141592

0x03 浮点数 “精度丢失” 问题

浮点数精度丢失是指在使用浮点数进行数值计算时,由于浮点数的二进制表示方式的特殊性,导致某些精确的数值无法准确表示,从而引起计算结果的误差。

浮点数在计算机中使用二进制表示,通常采用IEEE 754标准来表示单精度浮点数(32位)和双精度浮点数(64位)。无论是单精度还是双精度浮点数,都有固定的位数来表示整数部分和小数部分,这就导致了有些十进制数无法用有限的二进制位数准确表示。

例如,考虑一个简单的示例,计算 0.1 + 0.2。在十进制中,这个结果是 0.3,但是在浮点数表示中,由于 0.1 和 0.2 的二进制表示是无限循环的,所以它们的精确表示会受到限制。因此,计算机在进行浮点数计算时可能得到一个近似的结果,比如 0.30000000000000004。

浮点数精度丢失问题还可能在连续的计算中累积误差,导致最终结果的精度下降。这是由于浮点数的表示范围是有限的,无法表示所有的实数,因此在计算过程中可能会出现舍入误差和截断误差。

* 0x05 复数浮点型:complex_float / complex double

C99 标准新增了复数类型 _Complex 和虚部类型 _lmaginary

定义复数浮点型前需引入头文件 complex.h,定义格式如下:

#include <complex.h>

float complex a = 3.0 + 4.0 * I;
double complex b = 4.0 - 5.0 * I;

其中 I 表示虚数单位,complex 可以根据我们需要的精度定义。

C 语言不仅支持复数浮点型的加减乘除操作,还支持求模、求共轭等操作。

💬 代码演示:完成一些复数操作

#include <stdio.h>
#include <complex.h>

int main(void) 
{
    // 定义两个复数
    double complex num1 = 2.5 + 3.7 * I;
    double complex num2 = 1.8 - 2.3 * I;

    // 加法
    double complex sum = num1 + num2;
    printf("%.2f + %.2fi\n", creal(sum), cimag(sum));

    // 减法
    double complex diff = num1 - num2;
    printf("%.2f + %.2fi\n", creal(diff), cimag(diff));

    // 乘法
    double complex product = num1 * num2;
    printf("%.2f + %.2fi\n", creal(product), cimag(product));

    // 除法
    double complex quotient = num1 / num2;
    printf("%.2f + %.2fi\n", creal(quotient), cimag(quotient));

    // 求模
    double modulus = cabs(num1);
    printf("%.2f\n", modulus);

    // 求共轭
    double complex conjugate = conj(num1);
    printf("%.2f + %.2fi\n", creal(conjugate), cimag(conjugate));

    return 0;
}

🚩 运行结果如下:

4.30 + 1.40i
0.70 + 6.00i
13.01 + 0.91i
-0.47 + 1.45i
4.47
2.50 + -3.70i

Ⅱ. 二进制浮点数算术标准(IEEE754)

0x00 引入:浮点数的存储

在讲解之前我们先来试着观察下列程序的输出结果:

int main(void)
{
	int n = 9;

	float* pFloat = (float*)&n;
	printf("n的值为: %d\n", n);
	printf("*pFloat的值为 %f\n", *pFloat);

	*pFloat = 9.0;
	printf("num的值为: %d\n", n);
	printf("*pFloat的值为: %f\n", *pFloat);

	return 0;
}

🚩 运行结果如下:

❓ 思考:num 和 *pFloat 在内存中明明是同一个数,为什么浮点数和整数的结果会差这么大?

由此可以看出,浮点数和整数在内存中的存储方式一定是有区别的。

那么具体是什么样的区别?着我们就不得不去介绍开篇提到的 IEEE754 规定了。

0x01 IEEE754 规定

IEEE754 规定,任意一个二进制浮点数 \color{}V 可以表示成以下形式:

\color{}(-1)^S * M * 2^E

  • 其中, \color{}(-1)^s 表示符号位,当 \color{}s=0 时 \color{}V 为正数,当 \color{}s=1 时 \color{}V 为负数
  • \color{}M 表示有效数字,\color{}1\leq M< 2
  • \color{}2^E 表示指数位

💭 举个例子:浮点数 5.5

转换为二进制:

\color{}101.1\rightarrow 1.011 * 2^2\rightarrow (-1)^0*1.011*2^2

\color{}s=0,\, \, M=1.011,\, \, E=2

🔺 IEEE 754 规定:

对于 32 位浮点数,最高的 1 位是符号位 \color{}S,接着 8 位是指数 \color{}E,剩下的 23 位是有效数字 \color{}M

对于 64 位浮点数,最高的 1 位是符号位 \color{}S,接着 11 位是指数 \color{}E,剩下的 52 位是有效数字 \color{}M

IEEE 754 对有效数字M和指数E,还有一些特别规定!

前面说过, 1\leq M<2,也就是说,M 可以写成 1.xxxxxx 的形 式,其中 xxxxxx 表示小数部分。IEEE 754 规定,在计算机内部保存 M 时,默认这个数的第一位总是 1,因此可以被舍去,只保存后面的 xxxxxx 部分。 比如保存 1.01 的时候,只保存 01,等到读取的时候,再把第一位的1加上去。这样做的目的,是节省1位有效数字。以 32 位浮点数为例,留给 M 只有 23 位,将第一位的 1 舍去以后,等于可以保存 24 位有效数字。

至于指数 E,情况就比较复杂。 首先,E为一个无符号整数(unsigned int) 这意味着,如果E为8位,它的取值范围为0~255;如果E为11位,它的 取值范围为0~2047。但是,我们知道,科学计数法中的E是可以出现负数的,所以IEEE 754规定,存入内存时E的真 实值必须再加上一个中间数,对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023。比如,2^10的E 是10,所以保存成32位浮点数时,必须保存成10+127=137,即10001001。

然后,指数E从内存中取出还可以再分成三种情况:

E不全为0或不全为1

这时,浮点数就采用下面的规则表示,即指数E的计算值减去127(或1023),得到真实值,再将有效数字M前 加上第一位的1。 比如: 0.5(1/2)的二进制形式为0.1,由于规定正数部分必须为1,即将小数点右移1位, 则为1.0*2^(-1),其阶码为-1+127=126,表示为01111110,而尾数1.0去掉整数部分为0,补齐0到23位 00000000000000000000000,则其二进制表示形式为

0 01111110 00000000000000000000000

E全为0

这时,浮点数的指数E等于1-127(或者1-1023)即为真实值, 有效数字M不再加上第一位的1,而是还原为 0.xxxxxx的小数。这样做是为了表示±0,以及接近于0的很小的数字。

E全为1

这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s);

此时,再看前面的例子,问题就很好理解了: 

🔺 浮点数在内存中的分布:符号位 + 指数位 + 尾部部分

0x02 阅读:雷神之锤 III 源码中的 "平方根倒数速算法"

" evil floating point bit level hacking, what the fuck? "

—— Quake III

  (雷神之锤 III 游戏截图)

雷神之锤III 是由 id Software 采用 id Tech3 引擎制作的多人连线 FPS 游戏,1999年12月发行。玩家或独立或组队在地图中厮杀,死亡后数秒即在地图某处重生。当某位或某队玩家达到胜利条件或者游戏持续一定时间后即宣告一个回合结束。胜利条件取决于选择的游戏模式。

雷神之锤 III 的源码中有一段震惊四座的代码:

float Q_rsqrt( float number )
{
  long i;
  float x2, y;
  const float threehalfs = 1.5f;
  x2 = number * 0.5f;
  y  = number;
  i  = * ( long * ) &y;  // evil floating point bit level hacking
  i  = 0x5f3759df - ( i >> 1 ); // what the fuck?
  y  = * ( float * ) &i;
  y  = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration
  // y  = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed
  return y;
}

这是一个快速逆平方根的算法,求一个数的平方根的倒数。

\color{}f(x)=\frac{1}{\sqrt{x}}

常规的方法是调用 math 库里的 sqrt 求一个数的平方根,求平方根的倒数只需要:

float y = 1 / sqrt(x);

而作者实现的算法要比这种常规方法快得多,在计算浮点数的平方根倒数的同一精度的近似值时,此算法比直接使用浮点数除法要快四倍。其中还有一串神秘数字:0x5f3759df,更是给这段代码留下了最具神秘、浓墨重彩的一笔。还对它进行了位移,机器码位移,WTF?

该算法被称为 平方根倒数速算法 (Fast Inverse Square Root),对代码原理感兴趣的读者可以阅读下面这篇 wiki,有对该算法详细的讲解。

🔗 链接:Fast inverse square root

 Fast Inverse Square Root 的历史

Quake III Arena 是一款第一人称射击游戏,由id Software于 1999 年发布,并使用了该算法。Brian Hook 可能将 3dfx 的算法引入了 id Software。2000 年中国开发者论坛 CSDN 上出现了对该代码的讨论, 以及2002 年和 2003 年Usenet和 gamedev.net 论坛广泛传播了该代码。人们猜测谁编写了该算法和常数是如何导出的,有人猜测是约翰·卡马克。Quake III的完整源代码在QuakeCon 2005上发布,但没有提供答案。作者身份问题已于 2006 年得到解答。2007 年,该算法在一些使用现场可编程门阵列(FPGA)的专用硬件顶点着色器中实现。

Ⅲ. 浮点数类型的表达方式(Float Expression)

0x00 引入:浮点数类型的表示

符合 C 标准法的浮点数有两种表达形式,分别是 十进制小数型 和 指数型

0x01 十进制小数型:x.

十进制小数型:由数字和小数点组成:x.

💭 举个例子:下面这三种方式都是合法的:

123.     ✅
1.23     ✅
.123     ✅

小数点前后的数是可以省略的,小数点不可省略,省略了就不是浮点数了。

💬 代码演示:

#include <stdio.h>

int main(void)
{
    float a = 1.0;
    printf("%f\n", a);

    float b = 1.;
    printf("%f\n", b);

    float c = .1;
    printf("%f\n", c);

    return 0;
}

🚩 运行结果如下:

0x02 指数型:xEn

指数型:由字母 E 和数字组成(这里 e 也可以是小写):

\color{}xEn,\, \, \, \, \, \, \, \, \, \, \, \, x\in \mathbb{\mathbb{Z}},n\in \left \langle \textrm{float} \right \rangle

其中 x 必须是一个十进制小数型,和上面的规则一样,点的位置都是合法的。

n 必须是整型常量,且不能是表达式,并且 x 和 n 都不能省略。

💭 举个例子:只有前面 4 个是合法的

1.23e5         ✅ 
12345e6        ✅
3.14E7         ✅
.2e3           ✅
.e3            ❌ e 前面没有数
e3             ❌ e 前面没有数
3.14e          ❌ e 后面没有数
3.e6.2         ❌ e 后面必须是整数
5.0e(1+4)      ❌ 不能为表达式

指数型的表达方式非常苛刻,这里有一个口诀方便大家记忆:

" E 前 E 后必有数,E 后必定为整数。"

💬 代码演示:

#include <stdio.h>

int main(void)
{
    float a = .23e4;
    printf("%f\n", a);

    float b = 1234e6;
    printf("%f\n", b);

    float c = 3.14E7;
    printf("%f\n", c);

    return 0;
}

🚩 运行结果如下:

📌 [ 笔者 ]   王亦优 | 雷向明
📃 [ 更新 ]   2023.7.17
❌ [ 勘误 ]   /* 暂无 */
📜 [ 声明 ]   由于作者水平有限,本文有错误和不准确之处在所难免,
              本人也很想知道这些错误,恳望读者批评指正!

📜 参考文献:

- C++reference[EB/OL]. []. http://www.cplusplus.com/reference/.

- Microsoft. MSDN(Microsoft Developer Network)[EB/OL]. []. .

- 百度百科[EB/OL]. []. https://baike.baidu.com/.

- 维基百科[EB/OL]. []. https://zh.wikipedia.org/wiki/Wikipedia

- R. Neapolitan, Foundations of Algorithms (5th ed.), Jones & Bartlett, 2015.

- B. 比特科技. C/C++[EB/OL]. 2021[2021.8.31]

- 林锐博士. 《高质量C/C++编程指南》[M]. 1.0. 电子工业, 2001.7.24.

- 陈正冲. 《C语言深度解剖》[M]. 第三版. 北京航空航天大学出版社, 2019.

- 侯捷. 《STL源码剖析》[M]. 华中科技大学出版社, 2002.

- T. Cormen《算法导论》(第三版),麻省理工学院出版社,2009年。

- T. Roughgarden, Algorithms Illuminated, Part 1~3, Soundlikeyourself Publishing, 2018.

- J. Kleinberg&E. Tardos, Algorithm Design, Addison Wesley, 2005.

- R. Sedgewick&K. Wayne,《算法》(第四版),Addison-Wesley,2011

- S. Dasgupta,《算法》,McGraw-Hill教育出版社,2006。

- S. Baase&A. Van Gelder, Computer Algorithms: 设计与分析简介》,Addison Wesley,2000。

- E. Horowitz,《C语言中的数据结构基础》,计算机科学出版社,1993

- S. Skiena, The Algorithm Design Manual (2nd ed.), Springer, 2008.

- A. Aho, J. Hopcroft, and J. Ullman, Design and Analysis of Algorithms, Addison-Wesley, 1974.

- M. Weiss, Data Structure and Algorithm Analysis in C (2nd ed.), Pearson, 1997.

- A. Levitin, Introduction to the Design and Analysis of Algorithms, Addison Wesley, 2003. - A. Aho, J. 

- E. Horowitz, S. Sahni and S. Rajasekaran, Computer Algorithms/C++, Computer Science Press, 1997.

- R. Sedgewick, Algorithms in C: 第1-4部分(第三版),Addison-Wesley,1998

- R. Sedgewick,《C语言中的算法》。第5部分(第3版),Addison-Wesley,2002

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/38915.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

后端Long类型传到前端精度丢失的问题

问题出现&#xff1a;后端的Java Bean的id属性是用的Long类型对应数据库主键使用bigint类型&#xff0c;当使用JSON方式传递该数据给前端时&#xff0c;前端接收到的数据末尾会变成0。&#xff08;发生的精度丢失问题&#xff09; 问题原因&#xff1a;Java中的long能表示的范围…

谷歌黑客语法与漏洞寻找

谷歌黑客语法与漏洞寻找 一、常见的搜索引擎二、Google部分语法三、通配符四、FOFA五、Shodan六、例子&#xff1a;常见的后台地址 一、常见的搜索引擎 浏览器 浏览器是用来检索、展示以及传递Web信息资源的应用程序。 搜索引擎 所谓搜索引擎&#xff0c;就是根据用户需求与一…

SQL28 计算用户8月每天的练题数量

select day(date) as day,count(question_id) from question_practice_detail where month(date)8 and year(date)2021 group by date

谈一谈,Spring Boot 中的 starter 到底是什么 ?

1. 为什么要用Starter? 现在我们就来回忆一下&#xff0c;在还没有Spring-boot框架的时候&#xff0c;我们使用Spring 开发项目&#xff0c;如果需要某一个框架&#xff0c;例如mybatis&#xff0c;我们的步骤一般都是&#xff1a;到maven仓库去找需要引入的mybatis jar包&am…

【C++】-stack和queue的具体使用以及模拟实现(dqeue的介绍+容器适配器的介绍)

&#x1f496;作者&#xff1a;小树苗渴望变成参天大树&#x1f388; &#x1f389;作者宣言&#xff1a;认真写好每一篇博客&#x1f4a4; &#x1f38a;作者gitee:gitee✨ &#x1f49e;作者专栏&#xff1a;C语言,数据结构初阶,Linux,C 动态规划算法&#x1f384; 如 果 你 …

TCP四次挥手过程

TCP 断开连接是通过四次挥手方式。 双方都可以主动断开连接&#xff0c;断开连接后主机中的「资源」将被释放&#xff0c; 刚开始双方都处于 establised 状态&#xff0c;假如是客户端先发起关闭请求&#xff0c;过程如下图&#xff1a; 第一次挥手&#xff1a;客户端打算关闭…

【机器学习】基于卷积神经网络 CNN 的猫狗分类问题

文章目录 一、卷积神经网络的介绍1.1 什么是卷积神经网络1.2 重要层的说明1.3 应用领域二、 软件、环境配置2.1 安装Anaconda2.2 环境准备 三、猫狗分类示例3.1 图像数据预处理3.2 基准模型3.3 数据增强3.4 dropout层四、总结 一、卷积神经网络的介绍 1.1 什么是卷积神经网络 …

师承AI世界新星|7天获新加坡南洋理工大学访学邀请函

能够拜师在“人工智能10大新星”名下&#xff0c;必定可以学习到前沿技术&#xff0c;受益良多&#xff0c;本案例中的C老师无疑就是这个幸运儿。我们只用了7天时间就取得了这位AI新星导师的邀请函&#xff0c;最终C老师顺利获批CSC&#xff0c;如愿出国。 C老师背景&#xff1…

基于单片机的盲人导航智能拐杖老人防丢防摔倒发短息定位

功能介绍 以STM32单片机作为主控系统&#xff1b; OLED液晶当前实时距离&#xff0c;安全距离&#xff0c;当前经纬度信息&#xff1b;超声波检测小于设置的安全距离&#xff0c;蜂鸣器报警提示&#xff1a;低于安全距离&#xff01;超声波检测当前障碍物距离&#xff0c;GPS进…

【分布式系统案例课】查询服务设计、计数栈选型、总结

查询服务设计 数据获取路径 两个问题考虑&#xff1a; 1、老数据归档的问题。 如果所有分钟小时级的数据一直存在这个DB当中&#xff0c;那么DB的存储空间会被不断的消耗&#xff0c;性能也会不断的下降。所以一旦小时天月的数据聚合完成&#xff0c;我们就可以将一些老的原始…

TCP/IP网络编程 第十二章:I/O复用

基于I/O复用的服务器端 多进程服务器端的缺点和解决方法 为了构建并发服务器&#xff0c;只要有客户端连接请求就会创建新进程。这的确是实际操作中采用的种方案&#xff0c;但并非十全十美&#xff0c;因为创建进程时需要付出极大代价。这需要大量的运算和内存空间&#xff…

智慧校园能源管控系统

智慧校园能源管控系统是一种搭载了物联网技术、大数据技术、大数据等技术性智能化能源管理方法系统&#xff0c;致力于为学校提供更高效、安全性、可信赖的能源供应管理和服务。该系统包括了校内的电力工程、水、气、暖等各类能源&#xff0c;根据对能源的实时检测、数据统计分…

uni-app中a标签下载文件跳转后左上角默认返回键无法继续返回

1.首先使用的是onBackPress //跟onShow同级别 onBackPress(option){ uni.switchTab({ url:/pages/....... return true }) }发现其在uni默认头部中使用是可以的 但是h5使用了"navigationStyle":"custom"后手机默认的返回并不可以&#xff0c; 2.经过查询…

【MySQL技术专题】「问题实战系列」深入探索和分析MySQL数据库的数据备份和恢复实战开发指南(备份+恢复篇)

深入探索和分析MySQL数据库的数据备份和恢复实战开发指南 MySQL数据库备份全量备份全量备份应用场景 增量备份binlogbinlog主要作用binlog的作用主要有两个方面 开启binlog日志功能要开启MySQL的binlog日志步骤 mysqlbinlogmysqlbinlog的使用案例 全量备份与增量备份结合按天全…

WebRTC不同方案对比

1.功能上会有一些出入&#xff0c;尤其是国内的metaRTC版本迭代很快&#xff0c; 2.后续的ffmpeg也在进行支持webrtc特性&#xff0c;obs新的版本好像已经支持了webrtc&#xff0c; 3.对于webrtc部分缺少的信令部分的标准化也有了对应的标准whip和whep协议 所以&#xff0c;如…

好的CRM需要有哪些特点?

CRM客户管理系统在企业中占有举足轻重的地位&#xff0c;既是战略工具又可以强化部门间的团队协作、优化销售流程、缩短销售周期。市面上crm做得比较好的公司有哪些&#xff1f; 1.上榜Gartner魔力象限 好的CRM市场的引领、产品研发的持续投入、技术创新以及不断增长的市场份…

性能测试:Jmeter-Beanshell请求加密实例

目录 1. 打包加密方法Jar包&#xff0c;导入Jmeter 2. 加密参数 总结&#xff1a; 进行性能测试时&#xff0c;有可能遇到一种场景&#xff1a;接口请求由于安全问题&#xff0c;需要进行加密发送。 这种场景下&#xff0c;使用Jmeter实现性能测试&#xff0c;则也需要使用…

自学网络安全究竟该从何学起?

一、为什么选择网络安全&#xff1f; 这几年随着我国《国家网络空间安全战略》《网络安全法》《网络安全等级保护2.0》等一系列政策/法规/标准的持续落地&#xff0c;网络安全行业地位、薪资随之水涨船高。 未来3-5年&#xff0c;是安全行业的黄金发展期&#xff0c;提前踏入行…

Redis基本全局命令(含key过期策略)

Redis基本全局命令 KEYEXISTSDELEXPIRETTLRedis的key过期策略TYPE KEY 返回所有满⾜样式&#xff08;pattern&#xff09;的key。⽀持如下统配样式。 h?llo 匹配 hello , hallo 和 hxlloh*llo 匹配 hllo 和 heeeelloh[ae]llo 匹配 hello 和 hallo 但不匹配 hilloh[^e]llo 匹配…

使用Pandas计算两个系统客户名称的相似度

引言&#xff1a; 在日常业务处理中&#xff0c;我们经常会面临将不同系统中的数据进行匹配和比对的情况。特别是在涉及到客户管理的领域&#xff0c;我们需要确保两个系统中的客户记录是准确、一致和无重复的。 本文将介绍如何使用Python的Pandas库来处理这个问题。我们将以…