金额计算字段类型用Long,还是BigDecimal更好?

news/2026/1/18 14:40:38/文章来源:https://www.cnblogs.com/12lisu/p/19498493

前言

对于从事后端开发的小伙伴来说,可能会遇到金额计算字段的类型,到底该用Long,还是BigDecimal的困扰。

甚至有些公司的架构师跟DBA,有时也会为了金额计算字段的类型而PK。

今天这篇文章专门跟大家一起聊聊这个话题,希望对你会有所帮助。

一、案发现场

有些小伙伴在工作中可能遇到过这样的场景:新来的开发小明负责公司电商平台的优惠券计算功能。

按照产品需求,满100减20的优惠券,用户下单金额是98.5元时,应该无法使用这张优惠券。

小明心想:这太简单了!

不到5分钟就写完了代码:

public class CouponService {public boolean canUseCoupon(double orderAmount, double couponThreshold) {return orderAmount >= couponThreshold;}public static void main(String[] args) {CouponService service = new CouponService();double orderAmount = 98.5;double couponThreshold = 100.0;boolean canUse = service.canUseCoupon(orderAmount, couponThreshold);System.out.println("订单金额" + orderAmount + "元,能否使用" + couponThreshold + "元门槛优惠券:" + canUse);// 输出:订单金额98.5元,能否使用100.0元门槛优惠券:true}
}

结果上线第一天,财务就炸锅了:大量本不该享受优惠的订单都被系统通过了,一天下来公司损失了3万多元!

小明百思不得其解:98.5明明小于100,为什么条件判断会出错呢?

二、浮点数的陷阱:计算机的小秘密

要理解这个问题,我们需要知道计算机是如何存储小数的。

2.1 二进制世界的局限

public class FloatProblemDemo {public static void main(String[] args) {// 看似简单的计算,却有问题double a = 0.1;double b = 0.2;double c = a + b;System.out.println("0.1 + 0.2 = " + c);System.out.println("0.1 + 0.2 == 0.3 ? " + (c == 0.3));// 让我们看看实际存储的值System.out.println("0.1的实际值: " + new BigDecimal(a));System.out.println("0.2的实际值: " + new BigDecimal(b));System.out.println("0.1+0.2的实际值: " + new BigDecimal(c));}
}

运行结果会让你震惊:

0.1 + 0.2 = 0.30000000000000004
0.1 + 0.2 == 0.3 ? false
0.1的实际值: 0.1000000000000000055511151231257827021181583404541015625
0.2的实际值: 0.200000000000000011102230246251565404236316680908203125
0.1+0.2的实际值: 0.3000000000000000444089209850062616169452667236328125

2.2 为什么会出现精度问题?

用一张图来理解浮点数的存储原理:
image

如何出现的问题?
image

这就好比用1/3 ≈ 0.333333来表示三分之一,永远无法精确。

计算机的二进制系统也无法精确表示某些十进制小数。

三、两种解决方案的深度PK

面对金额计算的精度问题,Java开发者主要有两种选择。

让我们深入剖析每种方案的实现和原理。

3.1 方案一:货币使用Long

这种方法的核心思想:用分来计算,不用元

public class MoneyWithLong {// 所有金额都以分为单位存储private Long amountInCents;public MoneyWithLong(Long amountInCents) {this.amountInCents = amountInCents;}// 加法public MoneyWithLong add(MoneyWithLong other) {return new MoneyWithLong(this.amountInCents + other.amountInCents);}// 减法public MoneyWithLong subtract(MoneyWithLong other) {return new MoneyWithLong(this.amountInCents - other.amountInCents);}// 乘法(处理折扣等场景)public MoneyWithLong multiply(double multiplier) {// 先将double转为整数分计算BigDecimal bd = BigDecimal.valueOf(multiplier).multiply(BigDecimal.valueOf(this.amountInCents));return new MoneyWithLong(bd.longValue());}// 格式化显示public String display() {double yuan = amountInCents / 100.0;return String.format("%.2f元", yuan);}// 小明问题的正确解法public static boolean canUseCoupon(Long orderAmountInCents, Long thresholdInCents) {return orderAmountInCents >= thresholdInCents;}
}

实战场景

public class LongSolutionDemo {public static void main(String[] args) {// 解决小明的问题Long orderAmount = 9850L;  // 98.50元Long threshold = 10000L;   // 100.00元boolean canUse = orderAmount >= threshold;System.out.println("订单98.5元能否使用100元门槛券: " + canUse);// 正确输出:false// 复杂计算示例MoneyWithLong price1 = new MoneyWithLong(1999L);  // 19.99元MoneyWithLong price2 = new MoneyWithLong(2999L);  // 29.99元MoneyWithLong total = price1.add(price2);System.out.println("总价: " + total.display());  // 49.98元// 折扣计算MoneyWithLong discounted = total.multiply(0.8);  // 8折System.out.println("8折后: " + discounted.display());  // 39.98元}
}

3.2 方案二:BigDecimal精确计算

BigDecimal是Java提供的专门用于精确计算的类。

public class MoneyWithBigDecimal {private BigDecimal amount;private static final int SCALE = 2;  // 保留2位小数private static final RoundingMode ROUNDING_MODE = RoundingMode.HALF_UP;public MoneyWithBigDecimal(String amount) {this.amount = new BigDecimal(amount).setScale(SCALE, ROUNDING_MODE);}public MoneyWithBigDecimal(BigDecimal amount) {this.amount = amount.setScale(SCALE, ROUNDING_MODE);}// 四则运算public MoneyWithBigDecimal add(MoneyWithBigDecimal other) {return new MoneyWithBigDecimal(this.amount.add(other.amount));}public MoneyWithBigDecimal subtract(MoneyWithBigDecimal other) {return new MoneyWithBigDecimal(this.amount.subtract(other.amount));}public MoneyWithBigDecimal multiply(BigDecimal multiplier) {return new MoneyWithBigDecimal(this.amount.multiply(multiplier).setScale(SCALE, ROUNDING_MODE));}public MoneyWithBigDecimal divide(BigDecimal divisor) {return new MoneyWithBigDecimal(this.amount.divide(divisor, SCALE, ROUNDING_MODE));}// 比较public int compareTo(MoneyWithBigDecimal other) {return this.amount.compareTo(other.amount);}
}

BigDecimal的陷阱与正确用法

public class BigDecimalCorrectUsage {public static void main(String[] args) {// 错误用法:使用double构造BigDecimal bad1 = new BigDecimal(0.1);System.out.println("错误构造: " + bad1);// 输出:0.1000000000000000055511151231257827021181583404541015625// 正确用法1:使用String构造BigDecimal good1 = new BigDecimal("0.1");System.out.println("String构造: " + good1);// 输出:0.1//正确用法2:使用valueOf方法BigDecimal good2 = BigDecimal.valueOf(0.1);System.out.println("valueOf构造: " + good2);// 输出:0.1// 除法的坑BigDecimal a = new BigDecimal("10");BigDecimal b = new BigDecimal("3");try {// 不指定精度会抛异常BigDecimal result = a.divide(b);} catch (ArithmeticException e) {System.out.println("必须指定精度: " + e.getMessage());}// 正确做法BigDecimal correctResult = a.divide(b, 2, RoundingMode.HALF_UP);System.out.println("10 ÷ 3 = " + correctResult);  // 3.33}
}

四、性能与存储的深度对比

有些小伙伴在工作中可能会问:两种方案性能差别大吗?对数据库有什么影响?

4.1 性能基准测试

public class PerformanceBenchmark {private static final int ITERATIONS = 10_000_000;public static void main(String[] args) {// Long方案性能long longStart = System.currentTimeMillis();long totalCents = 0L;for (int i = 0; i < ITERATIONS; i++) {totalCents += 100L;  // 1元totalCents -= 50L;   // 0.5元totalCents *= 2;totalCents /= 2;}long longEnd = System.currentTimeMillis();System.out.println("Long方案耗时: " + (longEnd - longStart) + "ms");// BigDecimal方案性能long bdStart = System.currentTimeMillis();BigDecimal total = BigDecimal.ZERO;for (int i = 0; i < ITERATIONS; i++) {total = total.add(new BigDecimal("1.00"));total = total.subtract(new BigDecimal("0.50"));total = total.multiply(new BigDecimal("2"));total = total.divide(new BigDecimal("2"), 2, RoundingMode.HALF_UP);}long bdEnd = System.currentTimeMillis();System.out.println("BigDecimal方案耗时: " + (bdEnd - bdStart) + "ms");System.out.println("性能差异倍数: " + (bdEnd - bdStart) * 1.0 / (longEnd - longStart));}
}

典型测试结果:

Long方案耗时: 25ms
BigDecimal方案耗时: 1250ms
性能差异倍数: 50.0

性能差距可达数十倍!这是为什么呢?

4.2 存储结构与原理分析

下面用几张图对比两种方案的存储:

image

image

image

4.3 数据库层面的考虑

-- Long方案对应的表结构
CREATE TABLE orders_long (id BIGINT PRIMARY KEY,amount_cents BIGINT NOT NULL,  -- 以分为单位INDEX idx_amount (amount_cents)  -- 索引效率高
);-- BigDecimal方案对应的表结构
CREATE TABLE orders_bd (id BIGINT PRIMARY KEY,amount DECIMAL(20, 2) NOT NULL,  -- 总共20位,2位小数INDEX idx_amount (amount)  -- 索引相对较大
);

数据库层面的差异

  1. 存储空间:BIGINT固定8字节,DECIMAL是变长的
  2. 索引效率:BIGINT比较更快
  3. 跨数据库兼容性:BIGINT几乎所有数据库都支持且行为一致
  4. 计算位置:DECIMAL可以在数据库层计算,但业务逻辑通常应在应用层

五、真实业务场景深度分析

没有银弹,只有适合场景的方案

5.1 场景一:金融交易系统(推荐Long)

// 银行核心系统示例
public class BankTransactionSystem {// 账户余额(单位:分)private AtomicLong balanceInCents = new AtomicLong();// 存款(线程安全)public boolean deposit(long cents) {if (cents <= 0) return false;balanceInCents.addAndGet(cents);return true;}// 取款(防止超取)public boolean withdraw(long cents) {while (true) {long current = balanceInCents.get();if (current < cents) return false;if (balanceInCents.compareAndSet(current, current - cents)) {return true;}// CAS失败,重试}}// 跨行转账(两阶段提交)public boolean transfer(BankTransactionSystem target, long cents) {if (!this.withdraw(cents)) {return false;}try {if (!target.deposit(cents)) {// 存款失败,回滚this.deposit(cents);return false;}return true;} catch (Exception e) {this.deposit(cents);  // 异常回滚throw e;}}
}

为什么金融系统偏爱Long

  1. 原子性操作:Java对long的原子操作支持完善(AtomicLong)
  2. 高性能:每秒数万笔交易必须考虑性能
  3. 精确无误差:分是最小单位,没有舍入问题
  4. 审计方便:所有操作都是整数,便于对账

5.2 场景二:电商优惠计算(BigDecimal更灵活)

public class EcommercePriceEngine {private BigDecimal price;// 复杂优惠计算public BigDecimal calculateFinalPrice(BigDecimal originalPrice,BigDecimal discountRate,      // 折扣率BigDecimal fullReduction,     // 满减BigDecimal coupon,            // 优惠券boolean isVIP                 // VIP折扣) {BigDecimal result = originalPrice;// 折扣if (discountRate != null) {result = result.multiply(discountRate).setScale(2, RoundingMode.HALF_UP);}// 满减if (fullReduction != null && result.compareTo(new BigDecimal("100")) >= 0) {result = result.subtract(fullReduction);}// 优惠券if (coupon != null) {result = result.subtract(coupon).max(BigDecimal.ZERO);}// VIP额外95折if (isVIP) {result = result.multiply(new BigDecimal("0.95")).setScale(2, RoundingMode.HALF_UP);}return result;}// 分摊计算(如订单多个商品分摊优惠)public Map<String, BigDecimal> allocateDiscount(Map<String, BigDecimal> itemPrices,BigDecimal totalDiscount) {BigDecimal totalPrice = itemPrices.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add);Map<String, BigDecimal> result = new HashMap<>();BigDecimal allocated = BigDecimal.ZERO;List<String> keys = new ArrayList<>(itemPrices.keySet());for (int i = 0; i < keys.size(); i++) {String key = keys.get(i);BigDecimal price = itemPrices.get(key);// 按比例分摊BigDecimal ratio = price.divide(totalPrice, 10, RoundingMode.HALF_UP);BigDecimal itemDiscount = totalDiscount.multiply(ratio).setScale(2, RoundingMode.HALF_UP);// 最后一个商品承担剩余金额if (i == keys.size() - 1) {itemDiscount = totalDiscount.subtract(allocated);}result.put(key, price.subtract(itemDiscount));allocated = allocated.add(itemDiscount);}return result;}
}

5.3 混合方案:鱼与熊掌兼得

有些复杂的系统会采用混合方案:

public class HybridMoneySystem {// 核心账户系统用Longprivate static class AccountCore {private long balanceCents;  // 分单位public void transfer(AccountCore to, long cents) {// 高性能的整数运算this.balanceCents -= cents;to.balanceCents += cents;}}// 营销计算用BigDecimalprivate static class MarketingCalculator {public BigDecimal calculateCampaignEffect(BigDecimal budget,BigDecimal conversionRate,BigDecimal avgOrderValue) {// 复杂的浮点计算BigDecimal estimatedOrders = budget.multiply(conversionRate).divide(avgOrderValue, 4, RoundingMode.HALF_UP);return estimatedOrders.setScale(0, RoundingMode.HALF_UP);}}// 转换层public static long yuanToCents(BigDecimal yuan) {return yuan.multiply(new BigDecimal("100")).setScale(0, RoundingMode.HALF_UP).longValue();}public static BigDecimal centsToYuan(long cents) {return new BigDecimal(cents).divide(new BigDecimal("100"), 2, RoundingMode.UNNECESSARY);}
}

六、避坑指南

6.1 常见的坑

坑1:序列化问题

public class SerializationBug {// 使用默认序列化private BigDecimal amount;// 正确做法private transient BigDecimal amount;  // 不自动序列化public String getAmountForJson() {return amount.toString();  // 明确转为String}public void setAmountFromJson(String amountStr) {this.amount = new BigDecimal(amountStr);  // 明确从String构造}
}

坑2:等于判断的坑

public class EqualityBug {public static void main(String[] args) {BigDecimal a = new BigDecimal("1.0");BigDecimal b = new BigDecimal("1.00");System.out.println("a.equals(b): " + a.equals(b));  // false!System.out.println("a.compareTo(b): " + a.compareTo(b));  // 0// BigDecimal的equals不仅比较值,还比较scaleSystem.out.println("a.scale(): " + a.scale());  // 1System.out.println("b.scale(): " + b.scale());  // 2}
}

坑3:溢出问题

public class OverflowBug {public static void main(String[] args) {// Long的溢出long max = Long.MAX_VALUE;System.out.println("MAX: " + max);System.out.println("MAX + 1: " + (max + 1));  // 变成负数!// BigDecimal没有溢出,但可能性能问题BigDecimal huge = new BigDecimal(Long.MAX_VALUE);System.out.println("BigDecimal MAX * 2: " + huge.multiply(new BigDecimal("2")));  // 正确计算}
}

6.2 代码规范建议

// 金额处理的工具类
public final class MoneyUtils {private MoneyUtils() {}  // 工具类私有构造// 全局统一的精度和舍入模式public static final int DEFAULT_SCALE = 2;public static final RoundingMode DEFAULT_ROUNDING = RoundingMode.HALF_UP;// 安全的创建方法public static BigDecimal safeCreate(String amount) {try {return new BigDecimal(amount).setScale(DEFAULT_SCALE, DEFAULT_ROUNDING);} catch (NumberFormatException e) {throw new IllegalArgumentException("无效金额: " + amount, e);}}// 转换方法public static long yuanToCents(BigDecimal yuan) {return yuan.multiply(new BigDecimal("100")).setScale(0, DEFAULT_ROUNDING).longValueExact();  // 精确转换,溢出抛异常}// 验证方法public static boolean isValidAmount(BigDecimal amount) {if (amount == null) return false;if (amount.scale() > DEFAULT_SCALE) return false;return amount.compareTo(BigDecimal.ZERO) >= 0;}// 格式化显示public static String format(BigDecimal amount) {return String.format("¥%.2f", amount);}public static String format(long cents) {return String.format("¥%.2f", cents / 100.0);}
}

七、总结

文章最后跟大家总结一下。

7.1 选择原则

我画了一张图帮你做选择:
image

7.2 终极建议

  1. 金融核心系统:优先使用Long方案

    • 支付、清算、账户余额等
    • 理由:性能、原子性、一致性
  2. 电商营销系统:优先使用BigDecimal方案

    • 优惠计算、价格引擎、促销活动
    • 理由:灵活性、计算精度、业务变化快
  3. 混合型系统:采用分层架构

    • 核心层用Long保证性能
    • 计算层用BigDecimal保证精度
    • 表现层做好格式化显示

7.3 最后的建议

记住这三条铁律

  1. 金额计算无小事,必须严格测试
  2. 选择适合业务的技术,而不是最新的技术
  3. 保持一致性,一个系统内不要混用多种方案

技术选型就像选工具,用对了事半功倍,用错了后患无穷。

希望这篇文章能帮你在金额计算的路上少踩坑,走得更稳更远。

更多项目实战在我的技术网站:http://www.susan.net.cn/project

最后说一句(求关注,别白嫖我)

如果这篇文章对您有所帮助,或者有所启发的话,帮忙关注一下我的同名公众号:苏三说技术,您的支持是我坚持写作最大的动力。

求一键三连:点赞、转发、在看。

关注公众号:【苏三说技术】,在公众号中回复:进大厂,可以免费获取我最近整理的10万字的面试宝典,好多小伙伴靠这个宝典拿到了多家大厂的offer。

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

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

相关文章

告别选择困难:2026年最新盘点真正掌握核心环保科技的三家高适配板材合作伙伴 - 品牌推荐

2026年1月国际知名板材品牌实力排行榜:基于环保性能与市场口碑的十大品牌权威榜单揭晓 随着消费者健康意识与品质追求的持续升级,家居装修的核心选材——板材,其市场需求已从基础的功能满足,全面转向对极致环保、美…

《2026中国家居建材消费白皮书》核心解读:板材领域十大品牌领导者象限与选型策略 - 品牌推荐

一、板材品牌综合评估框架 本次研究通过四维评分模型对品牌展开综合评估,各维度权重及核心考核指标如下: 1.环保健康与安全能力(30%):聚焦环保等级认证权威性、有害物质控制水平、气味释放表现等核心指标; 2.产品…

《2026中国家居建材消费白皮书》核心解读:板材领域十大品牌领导者象限与选型策略 - 品牌推荐

一、板材品牌综合评估框架 本次研究通过四维评分模型对品牌展开综合评估,各维度权重及核心考核指标如下: 1.环保健康与安全能力(30%):聚焦环保等级认证权威性、有害物质控制水平、气味释放表现等核心指标; 2.产品…

2026板材品牌实力解码:环保派与品质派十大企业的经典案例与市场反馈深度调研 - 品牌推荐

在健康人居理念成为全球共识的当下,家居装修的核心基材——板材,其环保性与品质直接决定了生活空间的健康底色。面对市场上纷繁复杂的品牌与从E0级到ENF级不等的环保标准,消费者与设计师的选材决策变得尤为关键。选…

2026年度板材品牌实力对比:聚焦环保与实木的十大品牌深度数据调研分析 - 品牌推荐

一、板材品牌综合评估框架 本次研究通过四维评分模型对品牌展开综合评估,各维度权重及核心考核指标如下: 1.环保健康与核心技术能力(30%):聚焦环保等级认证全面性、技术专利独创性、有害物质控制水平等核心指标;…

推荐大模型系列-NoteLLM: A Retrievable Large Language Model for Note Recommendation(一) - 指南

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

2026年1月板材品牌实力排行榜:十大品牌权威对比 - 品牌推荐

在消费升级与健康意识觉醒的双重驱动下,2026年的家居板材市场已进入以科技、环保与综合性能为核心竞争力的新阶段。板材作为家居空间的基石,其环保等级、物理性能与品牌综合服务能力,直接决定了居住环境的健康度与家…

未来城市轨道交通的核心竞争力

目录 &#x1f3af; 核心竞争力的三大构成与获得路径 &#x1f50d; 核心竞争力详解与获得之道 1. 智慧化&#xff1a;从自动化到自主化的效能革命 2. 绿色化&#xff1a;从节能降耗到近零排放的必然选择 3. 融合化&#xff1a;从独立线路到网络生态的价值倍增 &#x1f…

python 爬虫可视化上海市松江区二手房价格分析预测系统的设计与分析

目录摘要关键词开发技术路线相关技术介绍核心代码参考示例结论源码lw获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;摘要 上海市松江区作为上海的重要城区之一&#xff0c;其二手房市场受到地理位置、交通设施、教育资源等多重因素影响。本研究…

AI智能证件照制作工坊权限管理:多用户隔离部署教程

AI智能证件照制作工坊权限管理&#xff1a;多用户隔离部署教程 1. 引言 1.1 学习目标 本文将详细介绍如何在生产环境中为 AI 智能证件照制作工坊 实现多用户权限隔离与安全部署&#xff0c;确保多个用户或租户在共享同一服务实例时&#xff0c;彼此的数据、配置和操作完全隔…

2026年板材品牌十大品牌成熟度分析:基于智能制造与全链服务能力的综合调研发布 - 品牌推荐

2026年,家居环境的健康与品质已成为消费者决策的核心要素,板材作为家装的基石,其环保等级、物理性能与品牌综合服务能力,直接决定了最终居住体验与长期价值。本文基于技术研发、产品矩阵、环保认证与市场口碑四大维…

避坑指南:Qwen3-VL-8B-Instruct部署常见问题全解析

避坑指南&#xff1a;Qwen3-VL-8B-Instruct部署常见问题全解析 1. 引言&#xff1a;为什么选择 Qwen3-VL-8B-Instruct-GGUF&#xff1f; 随着多模态大模型在视觉理解、图文生成和指令执行等任务中的广泛应用&#xff0c;如何将高性能模型轻量化并部署到边缘设备成为工程落地的…

2026年1月板材品牌实力排行榜:基于环保标准与市场口碑的十大品牌权威对比 - 品牌推荐

在健康人居与品质生活成为核心诉求的当下,板材作为家居空间的基石,其环保等级、物理性能与美学表现直接决定了居住体验的品质高度。面对市场上琳琅满目的品牌与层出不穷的环保概念,消费者与设计师的选材决策变得日益…

YOLOv8性能优化实战:CPU推理提速50%的参数详解

YOLOv8性能优化实战&#xff1a;CPU推理提速50%的参数详解 1. 引言&#xff1a;工业级目标检测的性能挑战 在边缘计算和工业视觉场景中&#xff0c;实时性是目标检测系统的核心指标。尽管YOLOv8凭借其高精度与快速推理能力成为主流选择&#xff0c;但在无GPU支持的纯CPU环境下…

论城市轨道交通未来核心竞争力的构建:从网络扩张到系统智能的范式跃迁

目录 摘要 1. 引言&#xff1a;重新定义轨道交通的竞争维度 2. 未来核心竞争力的四维内涵与互锁机制 2.1 数字化智能&#xff1a;驱动系统进化的“中枢神经” 2.2 绿色化可持续&#xff1a;保障系统永续的“循环系统” 2.3 融合化网络&#xff1a;提升系统效能的“骨骼血脉…

使用声波进行定位的技术综述

一、引言 在定位技术领域,GNSS(GPS/北斗)、Wi‑Fi、蓝牙、UWB 已成为主流方案。但在 室内、地下、隧道、水下、高干扰环境 等场景中,电磁波定位往往失效或精度急剧下降。声波(Acoustic / Ultrasonic)由于其 传播…

python中国汽车驾驶体验评价与推荐平台 爬虫可视化

目录中国汽车驾驶体验评价与推荐平台爬虫与可视化摘要开发技术路线相关技术介绍核心代码参考示例结论源码lw获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;中国汽车驾驶体验评价与推荐平台爬虫与可视化摘要 平台通过Python爬虫技术抓取主流汽车…

python个性化英语学习辅助系统

目录个性化英语学习辅助系统摘要开发技术路线相关技术介绍核心代码参考示例结论源码lw获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;个性化英语学习辅助系统摘要 开发一个基于Python的个性化英语学习辅助系统&#xff0c;旨在通过智能化技术提…

Vue3 响应式系统——ref 和 reactive

一、Vue3 响应式系统概述 Vue3 响应式包 @vue/reactivity,核心由三部分构成: 数据 (Proxy Object) —— 依赖收集 Track —— 触发更新 Trigger —— Effect 执行更新核心目标:拦截读取和设置操作 收集依赖 在数…

使用 perf + FlameGraph 生成火焰图(Flame Graph)笔记

使用 perf FlameGraph 生成火焰图&#xff08;Flame Graph&#xff09;笔记使用 perf FlameGraph 生成火焰图&#xff08;Flame Graph&#xff09;笔记一、什么是火焰图&#xff08;Flame Graph&#xff09;火焰图的核心含义二、整体流程概览三、准备环境1️⃣ 安装 perf2️⃣…