如何在数据库中存储小数:FLOAT、DECIMAL还是BIGINT?

news2024/11/17 13:53:25

前言

这里还是用前面的例子: 在线机票订票系统的数据表设计。此时已经完成了大部分字段的设计,可能如下:

CREATE TABLE flights (   
    flight_id INT AUTO_INCREMENT PRIMARY KEY,   
    flight_number VARCHAR(10),   
    departure_airport_code VARCHAR(3),   
    arrival_airport_code VARCHAR(3)
); 

考虑到还需要存储机票的订单金额,此时需要新增 price 字段来存储金额。金额一般都需要考虑小数,如99.99,而在MySQL中存储小数的方法其实有多种,比如:

  • FLOAT/DOUBLE:浮点数类型,能够直接存储小数,同时基本上不需要考虑数据范围

  • DECIMAL: 定点数类型,能够精确表示一个小数,比如直接存储99.99.

  • BIGINT: 可以将小数转换为整数,比如将99.99 转换为 9999, 然后将其保存到数据库当中

这里我们该如何选择,才能让数据库在实现需求的同时,也保证数据库的高性能呢? 下面我们先充分了解下所有可能的选择,在这个基础上再来对比比较,从而选出最为合适的类型。

数据类型

FLOAT/DOUBLE

FLOAT 和 DOUBLE 是浮点数类型,分别用于表示单精度和双精度浮点数。单精度浮点数 FLOAT 使用 32 位来存储一个浮点数,双精度浮点数DOUBLE 使用 64 位来存储一个浮点数。

其特点是能够表示非常大或非常小的数值。下面举一个例子,创建一个简单的数据表,其中包含几个 FLOAT 和 DOUBLE 类型的字段,以及一些示例数据,以展示这些数据类型能够表示的非常大和非常小的数值。

CREATE TABLE floating_point_values (     
    id INT AUTO_INCREMENT PRIMARY KEY,     
    small_float FLOAT,     
    large_float FLOAT,     
    small_double DOUBLE,     
    large_double DOUBLE 
);  

floating_point_values 的表,其中包含了四个列,具体含义如下:

  • small_float:用 FLOAT 类型来存储非常小的数值。

  • large_float:用 FLOAT 类型来存储非常大的数值。

  • small_double:用 DOUBLE 类型来存储非常小的数值。

  • large_double:用 DOUBLE 类型来存储非常大的数值。

然后往其中插入了一条记录,展示了 FLOAT 和 DOUBLE 类型能够表示的数值范围。

INSERT INTO floating_point_values (small_float, large_float, 
small_double, large_double) 
VALUES  (-3.402823466E+38,3.402823466E+38, 
-1.7976931348623157E+308, 1.7976931348623157E+308);

这些数值使用科学记数法表示,其中 E (或 e) 表示 10 的幂。例如,1.5E-45 表示 1.5 乘以 10 的 -45 次方,而 3.4E+38 表示 3.4 乘以 10 的 38 次方。下面简单查看插入到数据库中的数据:

mysql> select * from floating_point_values;
+----+-------------+-------------+-------------------------+------------------------+
| id | small_float | large_float | small_double            | large_double           |
+----+-------------+-------------+-------------------------+------------------------+
|  8 | -3.40282e38 |  3.40282e38 | -1.7976931348623157e308 | 1.7976931348623157e308 |
+----+-------------+-------------+-------------------------+------------------------+
1 row in set (0.03 sec)

可以看到,FLOAT 和 DOUBLE 可以表示非常小或者非常大的数值,使用该类型来存储数据,基本上不用考虑数据范围的问题。之所以能够存储这么大或者这么小的数,在于其底层是遵循 IEEE 754 标准,该标准定义了浮点数的存储和算术运算规则,这里关于 IEEE 754 标准的内容就不再展开,感兴趣的朋友可自行查阅资料。

但是这两种类型存在一个关键的问题,FLOAT 和 DOUBLE 不是精确的数值类型,可能会引入舍入误差。下面是一个经典的例子,在理想的情况下,0.1 + 0.2 应该等于 0.3,但是在执行这个查询时,结果可能会出人意料。

下面通过创建一个简单的表,展示这个例子,表结构定义如下:

-- 创建一个名为 prices 的表,其中包含两个 DOUBLE 类型的列
CREATE TABLE prices (   
    price1 DOUBLE,   
    price2 DOUBLE 
);  
-- 插入一些可能导致精度问题的值
INSERT INTO prices (price1, price2) VALUES (0.1, 0.2);  

通过查询表并检查两个价格 price1 和 price2 的和是否等于 0.3:

mysql> SELECT price1, price2, price1 + price2 AS total, (price1 + price2) = 0.3 AS IsEqual FROM prices; 
+--------+--------+---------------------+---------+
| price1 | price2 | total               | IsEqual |
+--------+--------+---------------------+---------+
|    0.1 |    0.2 | 0.30000000000000004 |       0 |
+--------+--------+---------------------+---------+

可以看到 price1 和 price2 的总和(即 total 列)实际上是一个略大于 0.3 的值,这是由于浮点数的精度问题导致的。因此,IsEqual 列显示为 0,表明 (price1 + price2) 的结果并不等于 0.3。

之所以存在精度问题的原因,这里也可以简单类比说明一下。在十进制系统中,有些分数不能精确表示(例如,1/3 等于 0.3333...,小数点后的 3 会无限重复)。

类似地,在二进制(基数为 2)系统中,有些十进制分数也不能被精确表示,因为它们在二进制中是无限循环小数。例如,十进制的 0.1 在二进制中会变成一个无限循环的分数:

0.1 (十进制) = 0.0001100110011001100110011001100110011... (二进制) 

由于计算机内存是有限的,浮点数类型必须在某一点截断这个无限循环,这就导致了精确度的丧失。

所以如果在处理涉及金融和需要高精度的数据时,应该避免使用FLOAT/DOUBLE类型,从而由于这种类型的舍入误差,导致系统出现问题。

DECIMAl

DECIMAL 类型与 FLOAT/DOUBLE 类型不同,DECIMAL 类型是一种定点数数据类型,它用于存储精确的数值,其在存储和计算时不会丢失精度,这使得它特别适合用于需要精确计算的应用场景。下面举个例子说明一下:

-- 创建一个名为 exact_prices 的表,其中包含两个 DECIMAL 类型的列
CREATE TABLE exact_prices (   
    price1 DECIMAL(10, 2),   
    price2 DECIMAL(10, 2) 
 );  
 -- 插入精确的十进制值
INSERT INTO exact_prices (price1, price2) VALUES (0.1, 0.2);  -- 查询表并检查两个价格的和是否等于 0.3
SELECT price1, price2, price1 + price2 AS total, (price1 + price2) = 0.3 AS IsEqual FROM exact_prices; 

执行上述插入和查询应该得到以下结果:

+--------+--------+-------+---------+
| price1 | price2 | total | IsEqual |
+--------+--------+-------+---------+
|   0.10 |   0.20 |  0.30 |       1 |
+--------+--------+-------+---------+

在这个例子中,与使用 FLOAT/DOUBLE 类型不同,price1 和 price2 的和恰好是 0.30,这是因为 DECIMAL 类型提供了精确的数值计算而不会引入浮点数的舍入误差。因此,IsEqual 列显示为 1,表明 (price1 + price2) 的结果确实等于 0.3。所以涉及金融和需要高精度的数据时,DECIMAL 类型是个更好的选择。

在声明 DECIMAL 类型时,可以指定精度(总共的数字个数)和标度(小数点后的数字个数)。格式为 DECIMAL(M, D),其中 M 是精度, 代表最多能够存储 D 是标度。

例如,DECIMAL(10, 2) 可以存储最大为 99999999.99 的数值,其中 整数位数最多为 M - D,也就是 10 - 2 = 8 位,而小数位数最多保存两位小数。下面举个例子来说明一下:

CREATE TABLE financial_records (     
    id INT AUTO_INCREMENT PRIMARY KEY,     
    transaction_amount DECIMAL(10, 2) -- 10位精度,其中包含2位小数 
);  

这个例子中,financial_records 表的 transaction_amount 字段被定义为 DECIMAL(10, 2) 类型,意味着可以存储最多 8 位整数和 2 位小数的数值。比如下面这个数据就能正常存入:

INSERT INTO financial_records(transaction_amount) VALUES (12345.67); 

如果小数位数超过2位,此时将会进行四舍五入,最终只会保存2位小数,示例如下:

mysql> INSERT INTO financial_records (transaction_amount) VALUES (12345.688);
Query OK, 1 row affected, 1 warning (0.03 sec)

mysql> select * from financial_records;
+----+--------------------+
| id | transaction_amount |
+----+--------------------+
|  3 |           12345.69 |
+----+--------------------+
1 row in set (0.03 sec)

DECIMAL 还有一个注意点,便是其在 MySQL 中是有长度限制的。在 MySQL 中 DECIMAL 类型的最大精度(即数字的总位数,包括小数点前后的数字)可以达到 65 位。这意味着 DECIMAL 类型的数字的总位数不能超过 65。

下面通过一个示例演示一下,看看 DECIMAL 的位数超过65位,此时会发生什么:

-- 创建一个名为 example_decimal 的表,包含一个 DECIMAL 类型的列
CREATE TABLE example_decimal (   
    amount DECIMAL(65, 30) -- 正确的 DECIMAL 定义 
);  

-- 尝试创建一个 DECIMAL 列,其精度超过了最大限制
CREATE TABLE example_decimal_too_large (   
    amount DECIMAL(66, 30) -- 错误的 DECIMAL 定义,因为精度超过了 65 
); 

可以看到,DECIMAL 的精度为65时,此时是能正常定义的;在第二个 CREATE TABLE 语句中,我们尝试创建一个精度为 66 的 DECIMAL 字段,此时将会报错,具体如下:

ERROR 1426 (42000): Too-big precision 66 specified for 'amount'. Maximum is 65.

从功能层面上看,DECIMAL可以在需要精确计算的场景,很好得满足我们的诉求。下面我们来看看 DECIMAL 和 FLOAT/DOUBLE 类型在存储空间和执行效率上的比较,看看在这精确性的要求下,我们会付出怎样的代价。

这里通过创建两个表,其中一个使用 DECIMAL 来存储数据,一个使用 DOUBLE 类型来存储数据:

-- 创建使用 DECIMAL 类型的表
CREATE TABLE decimal_table (   
    id INT AUTO_INCREMENT PRIMARY KEY,   
    decimal_col DECIMAL(30,10) 
 );
 -- 创建使用 DOUBLE 类型的表
 CREATE TABLE double_table (   
     id INT AUTO_INCREMENT PRIMARY KEY,   
     double_col DOUBLE 
 );  

然后使用存储过程往其中插入100w条数据,存储过程展示如下:

-- 创建存储过程插入数据
DELIMITER $$

CREATE PROCEDURE InsertData()
BEGIN
  DECLARE i INT DEFAULT 0;
  WHILE i < 1000000 DO
    INSERT INTO decimal_table (decimal_col) VALUES (RAND() * 1000000000.1234567890);
    INSERT INTO double_table (double_col) VALUES (RAND() * 1000000000.1234567890);
    SET i = i + 1;
  END WHILE;
END$$

DELIMITER ;

-- 调用存储过程来插入数据
CALL InsertData();

此时 decimal_table 和 double_table 表中都有100w条数据,我们下面将通过执行查询语句来比较 DECIMAL 和 FLOAT/DOUBLE 类型在存储效率、性能上的差异。

下面通过这个SQL查看 decimal_table 和 double_table 两张表占用的磁盘的大小:

mysql> SELECT  table_name AS 'Table',   round(((data_length + index_length) / 1024 / 1024), 2) 'Size in MB' FROM information_schema.TABLES WHERE table_schema = 'test' AND table_name in ('decimal_table', 'double_table');
+---------------+------------+
| Table         | Size in MB |
+---------------+------------+
| decimal_table |      38.56 |
| double_table  |      32.56 |
+---------------+------------+
2 rows in set (0.02 sec)

可以看到 decimal_table 占用的磁盘空间确实比 double_table 大一些,但是可以看到,其大小差距并不是很大,仅相差大约20%。

尽管 DECIMAL 使用了更多的字节来确保精确度,但由于其优化的存储方式,空间占用并没有显著增加。

事实上从 MySQL 5.0 开始,DECIMAL 类型的存储被优化为每4个字节存储9个十进制数字(对于小数点前的数字和小数点后的数字都是如此)。

不过这也意味着每个 DECIMAL 数字的存储大小是其精度的函数,而不是数值的大小。

下面我们来看看 DECIMAL 类型在性能上的表现。一般来说由于 DECIMAL 类型是用来进行精确的定点数计算的,它在处理和存储数据时通常会比 DOUBLE 类型慢。

下面我们编写一个Python脚本,会对前面定义的decimal_table 和 double_table 进行重复的数值运算,从而能够直观得展示二者的性能差异,脚本如下:

import mysql.connector
from time import time


# 定义数学运算函数
def math_operation_test(table_name, num_trials):
    if table_name == "decimal_table":
        update_query = f"UPDATE {table_name} SET decimal_col = decimal_col * 1.0000000001 WHERE id % 4 = 0;"
    else:
        update_query = f"UPDATE {table_name} SET double_col = double_col * 1.0000000001 WHERE id % 4 = 0;"

    total_time = 0
    for _ in range(num_trials):
        start_time = time()
        cursor.execute(update_query)
        cnx.commit()
        total_time += time() - start_time
    return total_time / num_trials, total_time  # 返回平均执行时间


if __name__ == '__main__':

    # 连接数据库
    db_config = {
        'user': 'user',
        'password': 'password',
        'host': 'hostname',
        'port': port,
        'database': 'test'
    }
    try:
        cnx = mysql.connector.connect(**db_config)
        cursor = cnx.cursor()

        # 定义测试次数
        num_trials = 100

        # 进行数学运算测试
        decimal_avg_time, decimal_total_time = math_operation_test('decimal_table', num_trials)
        double_avg_time, double_total_time = math_operation_test('double_table', num_trials)

        # 输出结果
        print(f"Average DECIMAL Math Operation Time: {decimal_avg_time} seconds")
        print(f"Average DOUBLE Math Operation Time: {double_avg_time} seconds")

        print(f"DECIMAL Math Total Operation Time: {decimal_total_time} seconds")
        print(f"DOUBLE Math Total Operation Time: {double_total_time} seconds")

        # 关闭连接
        cursor.close()
        cnx.close()

    except mysql.connector.Error as err:
        print(f"Error: {err}")

在这个脚本中,我们多次调用数学运算函数,取其每次计算的平均值以及总计算耗时,获得 decimal 和 double 这两种类型在高频率数学运算的差异:

Total DECIMAL Math Operation Time: 135.5842161178589 seconds
Total DOUBLE Math Operation Time: 118.5552248954773 seconds
Average DECIMAL Math Operation Time: 1.355842161178589 seconds
Average DOUBLE Math Operation Time: 1.185552248954773 seconds

可以看到DECIMAL 类型平均一次计算耗时需要1.38s,而DOUBLE 类型平均一次计算耗时为1.18s。

从这个对比结果可以看出 DECIMAL 类型的计算时间比 FLOAT 或 DOUBLE 类型的计算时间要长。这就是为了精确度而付出的性能代价。

整形

在实际开发中,BIGINT 类型也是常见的存储小数的一种方式,其既能具备 FLOAT/DOUBLE 类型的高性能,同时也能够拥有 DECIMAL 类型的准确性,使得其非常适合既需要高性能,也需要准确性的场景下使用。

这里关于 BIGINT 类型的存储效率,查询效率的对比验证,这里就不再展开,可以参考上面的对比过程。下面通过一个例子,展示其在获取高性能和精确性的情况下,不可避免带来代码复杂性的问题。

使用 BIGINT 存储小数的方法依赖于将小数转换为整数,下面举个例子来说明。这里需要一个字段来存储订单的金额,而这些金额通常有两位小数。这里使用 BIGINT 类型来存储的一个方式,是将金额放大100倍,以分为单位来进行存储:

CREATE TABLE financial_transactions (     
    id INT AUTO_INCREMENT PRIMARY KEY,     
    amount BIGINT  -- 金额以分为单位存储     
 ); 

在这个表中,amount 字段将用来存储以分为单位的金额,这样100分等于1元。所以这里需要在程序中对其进行转换。在插入数据时,需要在应用层将金额转换为分:

def insert_transaction(cursor, amount):
    # 将金额转换为分
    amount_in_cents = int(amount * 100)
    # 插入数据
    cursor.execute("INSERT INTO financial_transactions (amount) VALUES (%s)", (amount_in_cents,))
    
if __name__ == '__main__':
    # 连接数据库
    db_config = {
        # ... 这里省略
    }
    # 获取数据库连接
    cnx = mysql.connector.connect(**db_config)
    cursor = cnx.cursor()
    # 插入金额为100.20
    insert_transaction(cursor, 100.20)
    cnx.commit()

当查询要查询并显示金额时,此时需要将存储的分转换回来,这需要在应用层对其进行转换:

def get_transactions(cursor):
    cursor.execute("SELECT id, amount FROM financial_transactions")
    transactions = cursor.fetchall()
    for transaction in transactions:
        # 将分转换回金额
        amount_in_dollars = transaction[1] / 100.0
        print(
            f"Transaction ID: {transaction[0]}, Amount: {amount:.2f}")

所以虽然 BIGINT 类型既能保证精确性,也具备高性能。但是这不可避免增加了代码的复杂性,并增加了出错的可能性。

在使用 BIGINT 类型存储小数时,此时需要选择一个因数(比如100或1000)来乘以你的小数值,转换为整数。

这个因数决定了我们能够表示的小数精度。也必须确保在所有的计算中都使用同样的因数,这样才能保证计算的一致性和正确性。其次在查询展示时,也需要多一次转换才能获取到原本的数据。

从这里我们也可以看出来,没有一种数据类型是完美的,总是有权衡的。所以如果决定使用某种类型来存储数据时,需要确保自己已经综合考虑了各种因素。

怎么选择

在MySQL中存储小数方式,如上所述,可以选择FLOAT/DOULE 类型, DECIMAL 类型,也可以选择 BIGINT 类型。但是对于某一个业务场景来说,往往只有某一种类型在满足时间精度要求的前提下,在存储效率,查询性能上表现得更为优秀。

下面我们再汇总上面的内容,展示这几种类型在数据精度,存储效率,查询性能,代码复杂性等几个维度上的差异:

可以看到,由于 FLOAT/DOUBLE 存在精度丢失的问题,所以对于需要精确计算的场景,如金额存储,此时就不适合使用该种类型;

但是如果不需要精确计算的话,使用 FLOAT/DOUBLE 类型就非常合适,其能够表示非常大或非常小的数值,同时性能也比较好。

而 DECIMAL 提供精确的小数点运算,没有浮点数的舍入误差,就非常适合精确计算的场景,如金额存储。

相对的,DECIMAL 的运算可能会更慢。同时存储空间占用也会更多,尤其是在存储很多小数位数时。这也是其精确计算所需要付出的代价。

对于 BIGINT 类型,对于小数的存储,其存储效率高,同时性能也较好,但是不可避免会带来代码复杂性的提高,所以如果不是对性能特别敏感的场景,可以考虑使用 DECIMAL 类型。

回到最前面数据库设计的问题上,我这里这么金额字段的定义:

  • FLOAT/DOUBLE: 需要考虑金额的精确存储,此时不考虑

  • BIGINT: 并不需要进行大量的数学计算,对性能要求并没有特别敏感,不考虑

  • DECIMAL: 能够对金额进行精确存储,能够较好得满足需求

所以综合考虑之下,最终选择了 DECIMAL 类型来对金额进行存储:

CREATE TABLE flights (   
    flight_id INT AUTO_INCREMENT PRIMARY KEY,   
    flight_number VARCHAR(10),   
    departure_airport_code VARCHAR(3),   
    arrival_airport_code VARCHAR(3),
    price DECIMAL(10, 2) 
); 

DECIMAL(10, 2) 表示这个字段可以存储最高为10位数的数字,其中包括2位小数。这意味着最大的金额可以是 99999999.99,基本能够满足需求。

总结

在小数类型存储上,MySQL提供了多种类型的选择,如 FLOAT,DOUBLEDECIMALBIGINT 类型,都可以对小数进行存储。不过往往在某个场景下,只有一个类型才最满足要求。

本文详细介绍了各种数据类型,同时在数据精度,存储效率,执行效率,代码复杂性等维度上对其进行了比较,展示了其长处和相对应的缺点。

从而能够在数据库设计时,作出更准确,更高效的选择。

文章转载自:菜鸟额

原文链接:https://www.cnblogs.com/chenjiazhan/p/18071468

体验地址:引迈 - JNPF快速开发平台_低代码开发平台_零代码开发平台_流程设计器_表单引擎_工作流引擎_软件架构

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

HAProxy——高性能负载均衡器

目录 一.常见的Web集群调度器 二.HAProxy基本介绍 1.HAProxy是什么&#xff1f; 2.HAProxy的特性 3.HAProxy常用的8种负载均衡调度算法 3.1 轮询&#xff1a;RR&#xff08;Round Robin&#xff09; 3.2 最小连接数&#xff1a;LC&#xff08;Least Connections&#xff…

【TB作品】MSP430单片机,音乐播放器,四首音乐,八音盒,Proteus仿真

文章目录 题目要求仿真结果实验报告&#xff1a;基于MSP430单片机的八音盒设计实验目的实验设备实验原理总结 代码和仿真图 题目要求 八音盒 本设计利用MSP430单片机结合内部定时器及LED/LCD,设计一个八音盒,按下单键可以演奏预先设置的歌曲旋律。 基本要求: 使用LED/LCD显示器…

分销商城小程序开发可以为商家带来哪些好处

分销小程序的开发帮助商家更多地维系客户&#xff0c;市场竞争越来越激烈&#xff0c;各大商家争抢流量&#xff0c;拼命获客&#xff0c;小程序分销堪比商家的营销神器。 分销商城小程序是指商家通过小程序分销与分销商建立利润分享合作伙伴关系&#xff0c;允许分销商将参与小…

C语言例3-11:使用算术运算符的例子。

代码如下&#xff1a; int main(void) {int a12, b10;float c2.0, d0.5;double e6.5, f13.0;printf("-a %d\n",-a);printf("ab %d\n",ab);printf("a-b %d\n",a-b);printf("a*b %d\n",a*b);printf("a/b %d\n"…

第 7 场 小白入门赛

第5题 &#xff1a;兽之泪【算法赛】 AC_Code:C #include <iostream> #include <cstring> #include <algorithm> #include <vector> #include <queue> #include<stack> #include<cmath> #include <unordered_set> #include &…

【数据结构高阶】图

目录 一、图的基本概念 二、 图的存储结构 2.1 邻接矩阵 2.2.1 邻接矩阵存储模式的代码实现 2.2.2 邻接矩阵存储的优缺点 2.2 邻接表 2.2.1 无向图的邻接表 2.2.2 有向图的邻接表 2.2.3 邻接表存储模式的代码实现 2.2.4 邻接表存储的优缺点 三、图的遍历 3.1 图的…

[linux]信号处理:信号编码、基本API、自定义函数和集合操作的详解

一、信号的概述 1、定义 信号是 Linux 进程间通信的最古老的方式。信号是软件中断&#xff0c;它是在软件层次 上对中断机制的一种模拟&#xff0c;是一种异步&#xff08;不等待&#xff09;通信的方式 。信号可以导致一个正在运行的进程被 另一个正在运行的异步进程中断&a…

RHEL8部署baichuan2环境

前置 1、安装NVIDIA驱动 https://www.nvidia.cn/Download/index.aspx?langcn 阿里云 Alibaba Cloud Linux 3.2104 LTS 64位&#xff0c;需要选择RHEL8&#xff0c;如果没有RHEL8&#xff0c;则选最下面那个选择所有操作系统 点击搜索&#xff0c;下载这里有安装步骤&#x…

Datawhale【Sora原理与技术实战】| 学习笔记3

目录 一. 训练 Sora 模型二. 数据预处理三. 视频 VQVAE四. Diffusion Transformer 一. 训练 Sora 模型 Open-Sora 在下图中总结了 Sora 可能使用的训练流程&#xff1a; 链路: 二. 数据预处理 目前主流 LLM 框架缺乏针对 video 数据 统一便捷的管理和处理能力&#xff0c;…

天水麻辣烫:麻辣鲜香,地城风情尽在其中

天水麻辣烫&#xff0c;这道源自甘肃天水的地道美食&#xff0c;早已成为当地饮食文化中不可或缺的一部分。追溯其源头&#xff0c;它脱胎于上世纪80、90年代的麻辣粉&#xff0c;那时的麻辣粉&#xff0c;以土豆粉和土豆片为主&#xff0c;辅以香辣的油泼辣子&#xff0c;简单…

【C++ 】stack 和 queue

1. 标准库中的stack stack 的介绍&#xff1a; 1. stack是一种容器适配器&#xff0c;专门用在具有后进先出操作的上下文环境中&#xff0c;其删除只能从容器的一端进行 元素的插入与提取操作 2. stack是作为容器适配器被实现的&#xff0c;容器适配器即是对特定类封装作为其…

月结常见工单异常情况处理

1. 上月已经结算的工单&#xff0c;本月打开投料或者报工&#xff0c;或者增加产出 或者撤销报工修正报工 如果针对结算的订单&#xff0c;打开重新投料。 月末对工单重新结算&#xff0c;转出差异 KKS2单个处理&#xff08;KKS1集中处理&#xff09; 差异计算 KO88单个结算…

ThreadLocal基本原理

ThreadLocal基本原理 一、定义 ThreadLocal是java中所提供的线程本地存储机制&#xff0c;可以利用改机制将数据缓存在线程内部&#xff0c;该线程可以在任意时刻、任意方法中获取数据 二、底层原理 ThreadLocal底层是通过ThreadLocalMap来实现的&#xff0c;每个Thread对象中…

短剧APP系统开发:打造全新的掌上剧场体验

随着移动互联网的普及和人们娱乐方式的多样化&#xff0c;短剧已经成为现代人生活中不可或缺的一部分。为了满足用户对高质量、便捷观看短剧的需求&#xff0c;我们致力于开发一款功能全面、操作简便的短剧APP系统&#xff0c;为用户带来前所未有的掌上剧场体验。 一、系统开发…

AJAX 04 回调函数地狱和 Promise 链式调用、async 和 await、事件循环

AJAX 学习 AJAX 04 进阶01 同步代码和异步代码02 回调函数地狱和 Promise 链式调用(1) 回调函数地狱(2) Promise 链式调用(3) Promise 链式应用 03 async 和 await(1) async 和 await 使用(2) async函数和await捕获错误 04 事件循环-EventLoop(1) 事件循环(2) 事件循环练习(3) …

FREERTOS简介、移植和系统配置(基于STM32F103)

本文基础内容参考的是正点原子的FREERTOS课程。 这是基于HAL库的 正点原子手把手教你学FreeRTOS实时系统 这是基于标准库的 正点原子FreeRTOS手把手教学-基于STM32 基础知识&#xff0c;直接参考正点原子《FreeRTOS开发指南V1.1》基于标准库的&#xff0c;此处不再赘述。 本文…

SwiftUI的context Menu

SwiftUI的 context Menu 现在来演示一下如何使用 SwiftUI 的 Context Menu 。 代码&#xff1a; import SwiftUIstruct ContextMenuBootCamp: View {State var bgColor: Color .purplevar body: some View {VStack(alignment: .leading, spacing: 10.0) {Image(systemName: …

【LeetCode】升级打怪之路 Day 21:二叉树的最近公共祖先(LCA)问题

今日题目&#xff1a; 236. 二叉树的最近公共祖先1644. 二叉树的最近公共祖先 II235. 二叉搜索树的最近公共祖先 目录 LCA 问题LC 236. 二叉树的最近公共祖先 【classic】LC 1644. 二叉树的最近公共祖先 II 【稍有难度】LC 235. 二叉搜索树的最近公共祖先 ⭐⭐⭐ 今天做了几道有…

电源常用电路—驱动电路详解

数字电源控制核心对输入输出参数进行采集后&#xff0c;利用控制算法进行分析从而产生PWM控制信号&#xff0c;PWM信号将经过驱动电路的进行功率放大和隔离&#xff0c;随后接入功率开关器件从而完成电源的输出控制。本篇将主要针对电源的驱动电路进行讲解。 一、驱动电路概述…

高效Go编程: encoding/csv标准库深度解析

高效Go编程: encoding/csv标准库深度解析 引言了解encoding/csv库CSV文件的基本结构encoding/csv库的核心功能应用场景 读取CSV文件基本步骤代码示例处理不同的分隔符错误处理 处理CSV数据数据解析代码示例处理不规则数据代码示例 写入CSV文件基本步骤代码示例自定义设置错误处…