尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

d3 全精度浮点求和:d3.Adder、d3.fsum 与 d3.fcumsum 实战指南

d3 全精度浮点求和:d3.Adder、d3.fsum 与 d3.fcumsum 实战指南 d3 全精度浮点求和d3.Adder、d3.fsum 与 d3.fcumsum 实战指南【免费下载链接】d3Bring data to life with SVG, Canvas and HTML. :bar_chart::chart_with_upwards_trend::tada:项目地址: https://gitcode.com/GitHub_Trending/d3/d3本篇技术指南围绕 D3 中「全精度浮点数加法」这一专题展开覆盖d3.Adder累加器类、d3.fsum高精度求和与d3.fcumsum高精度累积求和三个 API 的完整用法、参数语义与典型示例。读完本文你将理解 IEEE 754 双精度加法为什么会丢失精度、D3 提供了哪些手段来补偿这种误差并能在数据汇总如体重总和、金额累加场景下正确选用fsum/fcumsum与sum/cumsum两套 API。为什么需要“全精度”加法JavaScript 的 Number 采用 IEEE 754 双精度浮点表示。当一个大数与一个极小的数相加时小数部分可能因位数有限而被直接舍掉例如在普通加法下1 1e-14的结果仍然是11e-14这一项“消失”了。如果之后再做1 - 1最终结果会是0而不是数学上正确的1e-14。同样地把0.1连续累加 10 次朴素加法会得到0.9999999999999999而不是数学上的1。D3 针对这个问题提供了专门的 API。对应文档 docs/d3-array/add.md 开篇即点明其定位Add floating point numbers with full precision以全精度方式对浮点数求和。在 D3 主包中这些 API 来自d3-array子模块package.json 声明的依赖为d3-array: ^3.2.4而 src/index.js 通过export * from d3-array将其完整透传。因此当你以常规方式引入主包时d3.Adder、d3.fsum、d3.fcumsum都可直接调用import * as d3 from d3; // d3.Adder、d3.fsum、d3.fcumsum 均由 d3-array 重新导出d3.Adder可复用的全精度累加器Adder是一个类形式的累加器适合在“数据分批到达、需要边到边加”的场景中复用同一个累加状态。new Adder()const adder new d3.Adder();创建一个初始值为0的新累加器。adder.add(number)adder.add(42)把指定的number加到累加器当前值上并返回累加器自身this因此支持链式调用const total new d3.Adder().add(0.1).add(0.1).add(0.1); console.log(total); // 0.3adder.valueOf()adder.valueOf() // 42返回累加器当前值的 IEEE 754 双精度表示。文档特别指出它的最佳用法是短写形式adder一元加号触发类型强制转换或者显式地Number(adder)const adder new d3.Adder(); for (const x of measurements) adder.add(x); const total adder; // 等价于 adder.valueOf() 与 Number(adder)d3.fsum一次性高精度求和fsum是对任意 iterable 求全精度总和的函数是朴素d3.sum的高精度替代品d3.fsum([0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]) // 1这正是朴素加法会输出0.9999999999999999的场景——fsum通过补偿机制保留了每一步的舍入误差最终还原出数学上精确的1。与d3.sum相同fsum也支持可选的accessor函数用于对对象数组求和。accessor 会被调用三次参数元素d、下标i和整个数组data其返回值参与累加d3.fsum(penguins, (d) d.body_mass_g) // 1437000文档给出的取舍建议是Although slower, d3.fsum can replace d3.sum wherever greater precision is neededfsum更慢但在需要更高精度的任何地方都可以替换d3.sum。也就是说它不是免费的——精度换性能二者按场景取舍。作为对照d3.sum 的文档明确说明其语义返回给定数字可迭代对象的和忽略undefined、null和NaN若可迭代对象中不含任何数字则返回0d3.sum([1, 2, 2, 2, NaN, 3, null]) // 10 d3.sum(penguins, (d) d.body_mass_g) // 1437000需要提醒的是fsum文档本身未逐条罗列缺失值处理细节在含缺失数据的真实数据上使用时建议先结合 d3-array 的源码与测试 确认边界行为或与d3.sum的结果交叉验证。d3.fcumsum高精度累积求和fcumsum返回一个Float64Array其中第i项是前i 1个数的全精度前缀和d3.fcumsum([1, 1e-14, -1]) // [1, 1.00000000000001, 1e-14]这个例子完整展示了补偿求和的价值朴素加法1 1e-14→1小项被舍入吞掉再1 (-1)→0fcumsum中间结果保留了1e-14的误差项最终第三项精确还原为1e-14。同样支持 accessor 形式返回的Float64Array长度与输入一致d3.fcumsum(penguins, (d) d.body_mass_g) // [3750, 7550, 10800, 10800, 14250, …]文档建议Although slower, d3.fcumsum can replace d3.cumsum when greater precision is needed。对照 d3.cumsum 的文档其语义为返回与输入等长的Float64Array前缀和忽略undefined与NaN便于跳过缺失数据无可加数字时返回全零d3.cumsum([1, 1, 2, 3, 5]) // [1, 2, 4, 7, 12] d3.cumsum(penguins, (d) d.body_mass_g) // [3750, 7550, 10800, 10800, …]fcumsum的典型应用是绘制带间隙的堆叠面积图或运行总量曲线当序列中混有极大和极小的量级如大额与小额订单交替时朴素cumsum的前缀和可能出现“平台被拉平、小增量丢失”的视觉误差而fcumsum能保持单调性可信。API 选型对照维度d3.sumd3.fsumd3.cumsumd3.fcumsum精度朴素 IEEE 754 累加全精度误差补偿朴素 IEEE 754 累加全精度误差补偿返回类型numbernumberFloat64ArrayFloat64Array缺失值undefined / null / NaN明确忽略文档未逐条罗列见上文说明明确忽略文档未逐条罗列无数字时返回 0—返回全零—性能快文档注明“slower”快文档注明“slower”替代关系—需要更高精度时替代 d3.sum—需要更高精度时替代 d3.cumsum经验法则金额、质量、测量值等“绝对误差敏感”的汇总用fsum/fcumsum对精度不敏感的计数类统计用sum/cumsum以获得更好的性能。仓库层面的佐证版本前提package.json 显示本仓库为 D37.9.0依赖d3-array ^3.2.4且要求 Node12engines字段fsum系列 API 在 D3 v7 的 ESM 结构下随d3-array一同导出以上用法适用于该版本区间。历史沿革CHANGES.md 记录了d3.fsum与d3.Adder自 D3 早期大版本起即作为 d3-array 的新增能力引入说明二者属于 D3 数组工具箱中的“老牌”高精度成员而非近期实验性 API。文档链接可验证性test/docs-test.js 会对docs目录下所有 Markdown 的相对链接与锚点做爬取校验链接必须指向真实存在的.md文件及{#anchor}锚点。本文引用的docs/d3-array/summarize.md#sum、#cumsum等锚点正是该测试所保障的目标形式。实现归属fsum/fcumsum的具体实现位于d3-array包文档中标注的源文件为该包内的src/fsum.jsAdder与fsum同源本仓库通过 src/index.js 的export * from d3-array透传因此本仓库内不含该算法的本地副本从文档描述与 D3 一贯的实现路线看其原理属于补偿求和compensated summation一类算法——在每一步加法中额外追踪被舍入掉的误差并在后续步骤回填这正是fcumsum([1, 1e-14, -1])末项能精确得到1e-14的原因。小结D3 用一组小而完整的 API 解决了浮点累加的精度痛点d3.Adder提供可链式复用的累加状态d3.fsum与d3.fcumsum分别对应d3.sum与d3.cumsum的全精度版本且保持相同的 accessor 调用约定d、i、data三参数。代价是更慢的速度收益是在“大数 小数”混合序列下不失真。汇总数据前先问一句这个总和里有没有量级相差超过 10 个数量级的项如果有切换到f前缀版本是零成本的正确性升级。【免费下载链接】d3Bring data to life with SVG, Canvas and HTML. :bar_chart::chart_with_upwards_trend::tada:项目地址: https://gitcode.com/GitHub_Trending/d3/d3创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表