news 2026/9/24 17:49:39

告别浮点误差!用decimal.js解决财务计算中的精度问题(附完整代码示例)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
告别浮点误差!用decimal.js解决财务计算中的精度问题(附完整代码示例)

告别浮点误差!用decimal.js解决财务计算中的精度问题(附完整代码示例)

如果你曾经在JavaScript里处理过钱,大概率踩过这个坑:0.1 + 0.2的结果不是0.3,而是一个让人哭笑不得的0.30000000000000004。这可不是什么程序员的冷笑话,而是浮点数表示法带来的经典精度问题。在普通的网页交互里,这点误差或许可以忽略不计,但一旦涉及到真金白银的财务计算,比如计算发票金额、处理分账、核算税金,哪怕是一分钱的偏差,都可能导致对账不平、报表错误,甚至引发严重的业务纠纷。很多开发者最初遇到这个问题时,会尝试用toFixed(2)来四舍五入,但这只是把问题掩盖了起来,并没有从根本上解决精度丢失的本质。今天,我们就来彻底解决这个问题,聊聊如何用decimal.js这个库,在JavaScript世界里实现真正可靠、精确的财务计算。

1. 为什么JavaScript的“数学”在钱面前会失灵?

要理解为什么需要decimal.js,我们得先搞清楚JavaScript内置的数字类型到底是怎么工作的。JavaScript里只有一种数字类型:Number。它遵循IEEE 754标准,是一种双精度64位二进制浮点数。这个名字听起来很复杂,但我们可以把它拆开来看。

“浮点数”意味着小数点可以“浮动”。它不像我们平时记账那样,固定小数点后两位。为了在有限的64位空间里表示极大或极小的数,它采用了科学计数法的思想。这64位被分成了三部分:

  • 1位符号位:表示正负。
  • 11位指数位:决定数值的范围大小。
  • 52位尾数位(有效数字):决定数值的精度。

问题就出在“二进制”和“十进制”的转换上。我们人类习惯的十进制小数,比如0.1,在二进制世界里是一个无限循环小数(类似于十进制的1/3)。计算机的尾数位长度是有限的,无法精确表示这个无限循环的数,只能进行舍入存储。当你对两个已经存在舍入误差的数进行运算时,误差就可能被放大,从而出现我们开头看到的那种反直觉的结果。

// 经典的精度陷阱 console.log(0.1 + 0.2); // 输出:0.30000000000000004 console.log(0.1 + 0.2 === 0.3); // 输出:false // toFixed只是表象修复,内部仍是浮点数 let result = (0.1 + 0.2).toFixed(2); // "0.30" console.log(parseFloat(result) === 0.3); // 输出:true,但这是字符串转换后的结果

在财务场景下,这种误差是致命的。想象一下一个电商分账系统,平台需要从一笔100元的订单中收取10%的服务费,剩下的90%给商家。

let orderAmount = 100; let platformRate = 0.1; let merchantRate = 0.9; let platformFee = orderAmount * platformRate; // 期望10元 let merchantIncome = orderAmount * merchantRate; // 期望90元 let totalCheck = platformFee + merchantIncome; // 期望100元 console.log(`平台服务费:${platformFee}`); // 输出:平台服务费:10 console.log(`商家收入:${merchantIncome}`); // 输出:商家收入:90 console.log(`合计校验:${totalCheck}`); // 输出:合计校验:100 // 看起来没问题?那是因为JavaScript控制台做了美化显示。实际值呢? console.log(platformFee.toPrecision(21)); // 输出:10.0000000000000000000 console.log(merchantIncome.toPrecision(21)); // 输出:90.0000000000000000000 // 在这个简单例子中,100 * 0.1 恰好能被二进制较好表示,误差极小。 // 但如果金额是 0.1 元,费率是 0.3 呢? let trickyFee = 0.1 * 0.3; console.log(trickyFee); // 输出:0.03 console.log(trickyFee.toPrecision(21)); // 输出:0.030000000000000002000 // 看,误差又出现了!虽然现在只有0.000000000000000002,但在成千上万次累加后,这个误差会累积成可观的数目。

注意toFixed()方法返回的是字符串,它确实能让显示结果看起来正确,但进行后续数值计算时,仍需转换回Number类型,精度问题依然存在。它不是一个可靠的财务计算解决方案。

2. 引入decimal.js:为JavaScript装上“精确”的引擎

既然原生的Number类型不可靠,我们就需要引入一个专门处理高精度十进制运算的库。decimal.js正是为此而生。它不是一个将数字包装一下的简单工具,而是自己实现了一套基于十进制的算术运算体系,完全避开了二进制浮点数的精度陷阱。

它的核心思想很简单:用字符串来表示和传递数值。因为字符串可以完整地保留我们输入的数字信息,不会在初始化阶段就引入误差。decimal.js内部会将这些字符串解析成它自己的数据结构,并进行精确的十进制运算。

与同类库的简单对比

特性decimal.jsbig.jsbignumber.js
核心优势功能全面,配置灵活,精度和舍入模式可动态设置API简洁,体积小,适合基础高精度计算decimal.js同源,但固定精度,不可动态修改
精度设置可动态配置(Decimal.set({ precision: 20 }))构造函数中静态设置构造函数中静态设置
体积较大最小中等
适用场景复杂的财务、科学计算,需要灵活配置简单的、精度要求固定的计算介于两者之间

对于财务系统这种对精度和灵活性要求都极高的场景,decimal.js通常是更合适的选择。你可以全局设置一个很高的精度(比如20位小数),确保所有计算都在这个安全范围内进行。

安装与引入

在你的项目中添加decimal.js非常简单:

# 使用 npm npm install decimal.js # 使用 yarn yarn add decimal.js # 使用 pnpm pnpm add decimal.js

引入方式也很灵活,支持多种模块化方案:

// ES Module (推荐用于现代前端项目) import Decimal from 'decimal.js'; // CommonJS (Node.js 环境或旧构建工具) const Decimal = require('decimal.js'); // 浏览器直接通过 script 标签引入 // <script src="https://cdn.jsdelivr.net/npm/decimal.js@10.4.3/decimal.min.js"></script> // 引入后,Decimal 作为全局变量使用

3. 核心API实战:像处理普通数字一样处理“钱”

decimal.js的API设计得非常直观,你会感觉就像在操作普通的数字,但背后却是精确无比的十进制计算。让我们从创建和基础运算开始。

创建Decimal对象创建时,强烈建议使用字符串作为参数,这是保证初始精度零误差的最佳实践。

import Decimal from 'decimal.js'; // 正确的创建方式:使用字符串 const price = new Decimal('19.99'); const quantity = new Decimal('3'); const taxRate = new Decimal('0.07'); // 7%的税率 // 也可以使用数字,但不推荐,因为数字本身可能已有误差 const notRecommended = new Decimal(0.1); // 内部存储的已经是二进制近似值了 console.log(notRecommended.toString()); // 输出:0.1 // 虽然toString显示0.1,但它的内部表示源于有误差的0.1 // 使用Decimal自己的静态方法 const fromAnotherDecimal = new Decimal(price); // 从另一个Decimal实例创建 const fromNumberSafely = Decimal.from(0.1); // 这也是安全的创建方式

四则运算所有运算方法都返回一个新的Decimal对象,符合不可变数据的理念。

const a = new Decimal('0.1'); const b = new Decimal('0.2'); // 加法 const sum = a.plus(b); console.log(sum.toString()); // 输出:'0.3' console.log(sum.equals(0.3)); // 输出:true // 减法 const diff = a.minus(b); console.log(diff.toString()); // 输出:'-0.1' // 乘法 const product = a.times(b); console.log(product.toString()); // 输出:'0.02' // 除法 const quotient = a.dividedBy(b); console.log(quotient.toString()); // 输出:'0.5' // 链式调用,非常流畅 const result = new Decimal('10') .plus('5') // 15 .times('2') // 30 .dividedBy('3') // 10 .minus('1'); // 9 console.log(result.toString()); // 输出:'9'

比较运算在财务中,比较金额是否相等、谁大谁小至关重要。永远不要用原生的===><来比较Decimal对象。

const amount1 = new Decimal('100.00'); const amount2 = new Decimal('100.00'); const amount3 = new Decimal('100.000001'); console.log(amount1.equals(amount2)); // true,精确相等 console.log(amount1.equals(amount3)); // false console.log(amount1.greaterThan(amount3)); // false console.log(amount1.lessThan(amount3)); // true console.log(amount1.greaterThanOrEqualTo(amount2)); // true console.log(amount1.comparedTo(amount3)); // 输出:-1 (表示小于)

舍入与格式化财务计算最终要展示给人看,或者存入数据库,这时就需要控制小数位数和舍入方式。decimal.js提供了强大的toDecimalPlaces方法和多种舍入模式。

const pi = new Decimal('3.1415926535'); // 保留两位小数,默认舍入模式为 ROUND_HALF_UP (四舍五入) const rounded = pi.toDecimalPlaces(2); console.log(rounded.toString()); // 输出:'3.14' // 使用不同的舍入模式 const roundedUp = pi.toDecimalPlaces(2, Decimal.ROUND_UP); // 向上取整 console.log(roundedUp.toString()); // 输出:'3.15' const roundedDown = pi.toDecimalPlaces(2, Decimal.ROUND_DOWN); // 向下取整 console.log(roundedDown.toString()); // 输出:'3.14' const roundedCeil = pi.toDecimalPlaces(2, Decimal.ROUND_CEIL); // 向正无穷取整 console.log(roundedCeil.toString()); // 输出:'3.15' // 财务中常见的“分”单位,即保留两位小数,四舍五入 function toCents(value) { return new Decimal(value).toDecimalPlaces(2, Decimal.ROUND_HALF_UP); } console.log(toCents('123.4567').toString()); // 输出:'123.46' console.log(toCents('123.4547').toString()); // 输出:'123.45'

提示Decimal.ROUND_HALF_UP是我们最熟悉的“四舍五入”,也是财务计算中最常用的标准。但有些国家的税务规则可能要求使用ROUND_HALF_EVEN(银行家舍入法),decimal.js也支持,使用前请确认业务规则。

4. 真实财务场景案例拆解

理论说再多,不如看几个实实在在的代码例子。我们来模拟几个典型的财务计算场景。

场景一:发票金额计算计算含税价、税额,并确保分项合计等于总额。

import Decimal from 'decimal.js'; // 假设我们有一张发票,包含多个项目 const invoiceItems = [ { name: '办公桌', unitPrice: '2999.99', quantity: '2' }, { name: '办公椅', unitPrice: '599.50', quantity: '4' }, { name: '台灯', unitPrice: '89.90', quantity: '3' }, ]; // 税率 13% const taxRate = new Decimal('0.13'); // 计算单项金额(单价 * 数量) const calculateItemTotal = (unitPrice, quantity) => { return new Decimal(unitPrice).times(quantity); }; // 计算税额(金额 * 税率) const calculateTax = (amount) => { return amount.times(taxRate); }; let subtotal = new Decimal(0); // 税前合计 let totalTax = new Decimal(0); // 税额合计 console.log('========== 发票明细 =========='); invoiceItems.forEach((item, index) => { const itemTotal = calculateItemTotal(item.unitPrice, item.quantity); const itemTax = calculateTax(itemTotal); const itemTotalWithTax = itemTotal.plus(itemTax); subtotal = subtotal.plus(itemTotal); totalTax = totalTax.plus(itemTax); console.log(`商品 ${index + 1}: ${item.name}`); console.log(` 单价: ¥${item.unitPrice}`); console.log(` 数量: ${item.quantity}`); console.log(` 税前小计: ¥${itemTotal.toFixed(2)}`); console.log(` 税额: ¥${itemTax.toDecimalPlaces(2).toFixed(2)}`); console.log(` 含税小计: ¥${itemTotalWithTax.toDecimalPlaces(2).toFixed(2)}`); console.log('---'); }); const grandTotal = subtotal.plus(totalTax); console.log('\n========== 发票汇总 =========='); console.log(`税前合计: ¥${subtotal.toDecimalPlaces(2).toFixed(2)}`); console.log(`税额合计: ¥${totalTax.toDecimalPlaces(2).toFixed(2)}`); console.log(`发票总额: ¥${grandTotal.toDecimalPlaces(2).toFixed(2)}`); // 校验:分项含税小计之和是否等于发票总额 let checkTotal = new Decimal(0); invoiceItems.forEach(item => { const itemTotal = calculateItemTotal(item.unitPrice, item.quantity); const itemTotalWithTax = itemTotal.plus(calculateTax(itemTotal)); checkTotal = checkTotal.plus(itemTotalWithTax); }); console.log(`\n校验总额: ¥${checkTotal.toDecimalPlaces(2).toFixed(2)}`); console.log(`总额是否一致: ${grandTotal.equals(checkTotal)}`); // 输出:true

场景二:多参与方分账系统这是一个更复杂的场景,比如一个电商平台,一笔订单的收入需要在平台、商家、推广者之间按比例分配,并且要处理“分”单位的精度(最小单位0.01元),确保分出去的钱总和等于订单总额。

import Decimal from 'decimal.js'; // 设置全局精度为20位,确保中间计算足够精确 Decimal.set({ precision: 20 }); class RevenueSharingSystem { constructor(orderAmount) { // 订单总金额,单位:元 this.orderAmount = new Decimal(orderAmount); // 参与方列表,包含名称和分账比例(0-1之间) this.parties = []; // 存储最终分账结果 this.distribution = {}; } addParty(name, ratio) { if (this.parties.some(p => p.name === name)) { throw new Error(`参与方 ${name} 已存在`); } this.parties.push({ name, ratio: new Decimal(ratio) }); } // 核心分账算法:处理最小单位(分)的精度和舍入 calculateDistribution() { const totalRatio = this.parties.reduce((sum, party) => sum.plus(party.ratio), new Decimal(0)); if (!totalRatio.equals(1)) { throw new Error(`所有参与方的分账比例之和必须为1,当前为:${totalRatio}`); } const amountInCents = this.orderAmount.times(100); // 转换为分,避免小数运算 let distributedCents = new Decimal(0); const results = {}; // 第一轮分配:按比例计算,并向下取整到分 for (const party of this.parties) { // 计算该方应得的分(可能带有多位小数) const rawCents = amountInCents.times(party.ratio); // 向下取整,得到初步分配的整数分 const allocatedCents = rawCents.floor(); results[party.name] = { rawAmount: rawCents.dividedBy(100), // 原始金额(元) allocatedAmount: allocatedCents.dividedBy(100), // 初步分配金额(元) allocatedCents: allocatedCents, // 初步分配的整数分 remainder: rawCents.minus(allocatedCents) // 余数(小于1分) }; distributedCents = distributedCents.plus(allocatedCents); } // 计算剩余未分配的分(由于向下取整,总和可能小于订单总金额的分) let remainingCents = amountInCents.minus(distributedCents); // 第二轮分配:将剩余的分(通常只有几厘)按余数大小分配给参与方 if (remainingCents.greaterThan(0)) { // 按余数从大到小排序 const sortedParties = [...this.parties].sort((a, b) => results[b.name].remainder.comparedTo(results[a.name].remainder) ); // 将剩余的每一分钱(1分)分配给余数最大的参与方 for (let i = 0; i < remainingCents.toNumber(); i++) { const party = sortedParties[i]; results[party.name].allocatedCents = results[party.name].allocatedCents.plus(1); results[party.name].allocatedAmount = results[party.name].allocatedCents.dividedBy(100); } } // 最终校验 let finalCheckCents = new Decimal(0); for (const party of this.parties) { finalCheckCents = finalCheckCents.plus(results[party.name].allocatedCents); } if (!finalCheckCents.equals(amountInCents)) { throw new Error(`分账校验失败!分配总额 ${finalCheckCents} 分不等于订单总额 ${amountInCents} 分`); } this.distribution = results; return this.distribution; } printDistribution() { console.log(`订单金额: ¥${this.orderAmount.toFixed(2)}`); console.log('--- 分账结果 ---'); for (const party of this.parties) { const info = this.distribution[party.name]; console.log(`${party.name} (比例: ${party.ratio.times(100).toFixed(2)}%):`); console.log(` 应得金额: ¥${info.rawAmount.toFixed(4)}`); console.log(` 实分金额: ¥${info.allocatedAmount.toFixed(2)}`); } // 计算并显示总和 const totalDistributed = this.parties.reduce( (sum, party) => sum.plus(this.distribution[party.name].allocatedAmount), new Decimal(0) ); console.log(`分账总额: ¥${totalDistributed.toFixed(2)}`); console.log(`总额校验: ${totalDistributed.equals(this.orderAmount) ? '通过' : '失败'}`); } } // 使用示例 const order = new RevenueSharingSystem('158.88'); // 一笔158.88元的订单 order.addParty('平台', '0.10'); // 平台抽成10% order.addParty('商家', '0.85'); // 商家获得85% order.addParty('推广员', '0.05'); // 推广员获得5% const dist = order.calculateDistribution(); order.printDistribution();

这个分账系统示例展示了在真实业务中如何处理“分”这个最小货币单位,以及如何公平地处理因舍入产生的微小差额。它确保了:

  1. 每个参与方分到的钱都是整数“分”。
  2. 所有参与方分到的钱加起来,一分不多,一分不少,正好等于订单总额。
  3. 当出现无法整除的“厘”时,按照比例计算的余数大小进行分配,相对公平。

5. 集成、性能与最佳实践

decimal.js集成到现有项目中,并确保其高效稳定运行,还需要注意以下几点。

与现有代码库的兼容性你的项目里可能已经有成千上万行使用普通Number类型进行计算的代码。全部重写是不现实的。一个务实的策略是划定边界

  • 输入/输出边界:在所有从外部(用户输入、API接口、数据库)接收货币数值的地方,立即将其转换为Decimal类型(使用字符串构造)。
  • 核心计算层:所有涉及金额计算、税率计算、分账逻辑的业务代码,全部使用Decimal类型进行计算。
  • 持久化/展示边界:在将金额存入数据库或返回给前端时,将其转换为字符串或固定小数位的数字(例如使用.toFixed(2))。数据库存储建议使用DECIMALNUMERIC类型字段。

你可以创建一个简单的工具函数来统一处理转换:

// utils/decimalUtils.js import Decimal from 'decimal.js'; // 安全地创建Decimal,优先使用字符串 export function toDecimal(value) { if (value instanceof Decimal) { return value; } if (typeof value === 'string') { // 可以在这里添加字符串格式校验 return new Decimal(value); } // 如果是数字,先转换成字符串以避免二进制误差,但最好从源头就用字符串 return new Decimal(value.toString()); } // 格式化金额为显示字符串(保留两位小数) export function formatMoney(decimalValue) { return `¥${decimalValue.toDecimalPlaces(2, Decimal.ROUND_HALF_UP).toFixed(2)}`; } // 在业务计算中 import { toDecimal, formatMoney } from './utils/decimalUtils.js'; function calculateTotal(items) { let total = new Decimal(0); items.forEach(item => { // 假设item.price和item.quantity可能来自API,是字符串或数字 const price = toDecimal(item.price); const quantity = toDecimal(item.quantity); total = total.plus(price.times(quantity)); }); return total; }

性能考量Decimal对象运算比原生的Number运算要慢,因为它是在JavaScript层面实现的复杂运算,而不是CPU指令。但对于绝大多数财务应用,这个性能开销是完全可以接受的,因为财务计算的频率和数量级远低于图形渲染或科学计算。

注意:在极少数需要处理海量高频金融数据(如实时行情计算)的场景下,可能需要评估性能影响。但对于订单处理、报表生成、税金计算等业务,decimal.js的性能绰绰有余。正确性永远优先于性能,尤其是在涉及钱的场景。

常见陷阱与调试技巧

  1. 不要混用类型:一旦决定使用Decimal,在同一个计算链条中就不要穿插使用原生的Number。这会导致精度丢失,前功尽弃。
    // 错误示例 const a = new Decimal('10.00'); const b = 0.1; // 原生Number const result = a.plus(b); // Decimal.js 会处理,但b的精度问题在传入时已存在 console.log(result.toString()); // 输出:'10.1',但b的误差可能影响后续计算 // 正确做法 const correctResult = a.plus(new Decimal('0.1'));
  2. 善用.toString().toNumber()Decimal对象不能直接用于console.log拼接或模板字符串,需要先转换。
    const money = new Decimal('123.456'); console.log(`金额是:${money}`); // 输出:金额是:[object Object] console.log(`金额是:${money.toString()}`); // 输出:金额是:123.456 console.log(`金额是:${money.toFixed(2)}`); // 输出:金额是:123.46 // 谨慎使用 toNumber(),转换回Number可能重新引入浮点误差 console.log(money.toNumber()); // 输出:123.456
  3. 设置合理的全局精度:在应用入口处,根据业务需要设置全局精度。财务计算通常设置precision为 20 左右就非常安全了。
    // 在应用初始化时设置 Decimal.set({ precision: 20, rounding: Decimal.ROUND_HALF_UP, // 设置全局默认舍入模式 toExpNeg: -7, // 科学计数法显示阈值 toExpPos: 21 });

测试策略对于财务代码,完善的测试至关重要。你需要为所有涉及Decimal计算的核心函数编写单元测试。

// 使用 Jest 测试框架示例 import Decimal from 'decimal.js'; import { calculateTax, formatMoney } from './financialUtils'; describe('财务工具函数测试', () => { test('calculateTax 应正确计算税额', () => { const amount = new Decimal('100.00'); const taxRate = new Decimal('0.13'); const tax = calculateTax(amount, taxRate); expect(tax.toString()).toBe('13.00'); // 使用 Decimal.equals 进行比较 expect(tax.equals(new Decimal('13.00'))).toBe(true); }); test('formatMoney 应正确格式化金额', () => { const value1 = new Decimal('123.456'); expect(formatMoney(value1)).toBe('¥123.46'); const value2 = new Decimal('99.995'); expect(formatMoney(value2)).toBe('¥100.00'); // 测试四舍五入 }); test('分账系统应确保总额平衡', () => { const system = new RevenueSharingSystem('100.00'); system.addParty('A', '0.333333'); system.addParty('B', '0.333333'); system.addParty('C', '0.333334'); // 比例之和为1 const dist = system.calculateDistribution(); // 验证三方分配之和等于100元 const total = Object.values(dist).reduce((sum, d) => sum.plus(d.allocatedAmount), new Decimal(0)); expect(total.equals(new Decimal('100.00'))).toBe(true); }); });

在我自己构建的几个电商后台系统中,引入decimal.js彻底解决了月末对账时那些令人头疼的“几分钱差异”问题。最大的体会是,在财务领域,信任必须建立在确定性的基础上。原生的浮点数计算充满了不确定性,就像在沙地上盖房子。而decimal.js提供了一种确定性的、符合人类直觉的十进制计算模型,让每一分钱的来龙去脉都清晰可循。从“能用”到“可靠”,往往就是这些基础工具的选择决定的。如果你的系统正在或即将处理任何与钱相关的数据,那么今天就是开始使用decimal.js的最佳时机。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/24 17:49:26

避坑指南:Coze图像生成插件中90%人都会忽略的5个关键设置

避坑指南&#xff1a;Coze图像生成插件中90%人都会忽略的5个关键设置 你是否曾满怀期待地在Coze中构思好一幅画面&#xff0c;输入了精心准备的提示词&#xff0c;但最终生成的图像却总感觉“差那么点意思”&#xff1f;或许画面构图有些别扭&#xff0c;或许风格融合得不够自然…

作者头像 李华
网站建设 2026/9/24 17:49:29

PCB设计实战:5种阻抗匹配方法消除信号反射(附真实案例对比)

PCB设计实战&#xff1a;5种阻抗匹配方法消除信号反射&#xff08;附真实案例对比&#xff09; 信号反射&#xff0c;这个在低速电路设计中几乎可以忽略的“幽灵”&#xff0c;一旦进入GHz级别的数字世界&#xff0c;就会立刻显露出它的破坏力。我至今还记得第一次调试一块DDR4…

作者头像 李华
网站建设 2026/9/24 17:49:38

8253/8254定时器在嵌入式系统中的应用:从原理到实战代码解析

8253/8254定时器&#xff1a;在现代嵌入式系统中的实战应用与深度解析 如果你是从8051、AVR或者STM32这类现代单片机入门的嵌入式开发者&#xff0c;第一次听说8253或8254这个型号时&#xff0c;可能会觉得它是个“古董”。确实&#xff0c;作为上世纪七八十年代诞生的经典可编…

作者头像 李华
网站建设 2026/9/20 6:57:15

YOLO26改进73:全网首发--c3k2模块添加PoolingFormerCGLU创新模块

论文介绍 MetaFormer(Transformer的抽象架构)已被证实对实现强劲性能具有重要作用。本文进一步探索MetaFormer的潜力,再次聚焦于无需精心设计token mixer的特性:基于MetaFormer框架引入数种采用最基础或常见mixer的基线模型,主要发现如下: (1)MetaFormer确保性能的坚实…

作者头像 李华