MATLAB循环中动态变量名创建:从eval到结构化数据存储的工程实践
1. 项目概述为什么我们需要动态变化的变量名在MATLAB的日常数据处理和批量仿真中我们经常会遇到一个看似简单却让人头疼的场景你需要处理几十甚至上百组数据每组数据都需要独立存储并且你希望它们的变量名能像data_1,data_2,data_3... 这样有规律地自动生成。或者你在一个循环中生成了一系列中间结果图想把它们分别保存为figure_001.png,figure_002.png...。新手的第一反应往往是手动写死变量名但这在数据量稍大时就变得不可行且极易出错。这正是“for循环变量名变化”要解决的核心痛点实现程序化、批量化的变量创建与管理。它背后的需求非常普遍从科学计算中的参数扫描、机器学习中的交叉验证折叠数据存储到工程仿真中的多工况结果保存都离不开这个基础但关键的技巧。网络上大量的相关搜索如“批量预加载”、“循环内逐条查询”都指向了在循环中高效组织数据的共同诉求。然而实现这个目标有两条主要路径它们的选择直接关系到代码的健壮性、可读性和执行效率。一条是广为人知但备受争议的eval函数路径另一条则是更现代、更安全的数据结构化存储路径。本文将深入探讨这两种方法的原理、具体实现、各自的“坑”并分享我在多年工程实践中总结出的最佳策略和独家避坑技巧。2. 核心思路解析eval的诱惑与结构化的理性当我们想在循环中创建var1,var2,var3这样的变量时最直观的想法就是用字符串拼接出变量名然后执行它。MATLAB 的eval函数正是为此而生。2.1eval函数的工作原理与潜在风险eval的功能是执行一个包含MATLAB表达式或语句的字符串。在循环中我们可以这样使用它for i 1:5 var_name [result_, num2str(i)]; % 动态生成变量名字符串如 result_1 eval([var_name, i * 10;]); % 执行字符串等价于在命令行输入 result_1 10; end执行后工作区会出现result_1到result_5五个独立的变量。这看起来完美地解决了问题。但是资深用户对eval往往避之不及原因在于它的几大硬伤极差的调试体验当eval执行的语句出错时报错信息指向的是eval这一行而不是实际出错的动态代码内容让你像在黑暗中摸索。代码可读性灾难大量使用eval的代码其逻辑被隐藏在字符串中其他人甚至几天后的你自己很难理解。性能瓶颈MATLAB 的 JIT即时编译加速器无法优化eval中的代码因为它是在运行时才被解释的。在大型循环中这会导致显著的性能下降。安全风险如果拼接的字符串来源于不可信的输入如用户输入、文件读取可能意外执行恶意代码。注意尽管有这些风险在极少数特定场景下如动态构造复杂的、无法预先确定的函数调用eval仍有其存在价值。但对于单纯的“循环创建变量名”我们有更好的选择。2.2 结构化数据存储更优解的思维转变与其创建一堆分散的、名字相似的变量不如思考这些本质上同类的数据是不是应该放在一个统一的数据容器里管理这就是结构化思维的起点。MATLAB 提供了几种强大的容器元胞数组可以存储任意类型、任意大小的数据。results{1}就对应原来的result_1。结构体数组可以为每个数据条目附加有意义的字段名。例如results(1).value。表格如果数据是规整的、列对齐的表格是最佳选择它自带列名和行名支持强大的数据操作。这种转变的优势是压倒性的可维护性所有数据在一个变量中传递、保存、加载都非常方便。可操作性你可以轻松地对整个数据集进行向量化操作、批量绘图或统计分析无需再写一个循环去访问每个独立变量。清晰性代码意图一目了然。在接下来的实操中我将对比展示两种方式的代码并详细解释为何在99%的情况下你都应该选择后者。3. 两种方法的详细实现与对比让我们通过一个具体的例子来实践模拟一个实验循环10次每次实验生成一组随机数据并计算其均值和标准差我们需要保存每次实验的原始数据、均值、标准差以及一张预览图。3.1 使用eval的实现方式不推荐仅作演示% 不推荐的方法使用 eval num_experiments 10; data_length 100; for exp_idx 1:num_experiments % 1. 生成实验数据 exp_data randn(data_length, 1) exp_idx; % 每次实验的基线不同 % 2. 计算统计量 exp_mean mean(exp_data); exp_std std(exp_data); % 3. 动态创建变量名并赋值 - 这里是危险区 eval([data_raw_, num2str(exp_idx), exp_data;]); eval([result_mean_, num2str(exp_idx), exp_mean;]); eval([result_std_, num2str(exp_idx), exp_std;]); % 4. 绘图并保存同样使用了eval动态生成文件名 fig figure(Visible, off); plot(exp_data); title(sprintf(Experiment %d, Mean%.2f, exp_idx, exp_mean)); img_filename sprintf(figure_%03d.png, exp_idx); eval([print(fig, -dpng, -r150, img_filename );]); % 注意这里print函数本身可以通过变量调用eval是不必要的。这里演示了一种更错误的嵌套eval用法。 close(fig); % 一个更常见的错误试图在后续用eval访问这些变量 % eval([fprintf(Mean of exp %d: %.2f\n, exp_idx, result_mean_, num2str(exp_idx), );]); end % 尝试使用第5次实验的数据你需要知道确切的变量名。 % 如果想对所有均值做图你需要写一个循环再次使用eval来获取每个变量。 plot_data []; for exp_idx 1:num_experiments eval([plot_data [plot_data, result_mean_, num2str(exp_idx), ];]); end figure; plot(plot_data, o-); title(Mean of Each Experiment (eval method));这段代码的问题暴露无遗工作区被data_raw_1,result_mean_1, ... 等30个变量污染难以管理。后续任何想要使用这批数据的操作都必须再写一个循环配合eval代码冗余且危险。第4步中的eval用于print函数是完全多余的print(fig, -dpng, -r150, img_filename)即可这显示了eval的滥用会让人写出违背常理的代码。想象一下如果循环中途因为exp_data计算错误而崩溃调试将是噩梦。3.2 使用元胞数组的实现方式推荐% 推荐的方法使用元胞数组 num_experiments 10; data_length 100; % 预分配元胞数组这是提升性能的关键习惯 all_raw_data cell(1, num_experiments); % 存储原始数据 all_means zeros(1, num_experiments); % 存储均值用数值数组更高效 all_stds zeros(1, num_experiments); % 存储标准差 for exp_idx 1:num_experiments % 1. 生成实验数据 exp_data randn(data_length, 1) exp_idx; % 2. 计算统计量 exp_mean mean(exp_data); exp_std std(exp_data); % 3. 存储到预分配的结构中 - 清晰、直接、高效 all_raw_data{exp_idx} exp_data; % 使用花括号{}访问元胞内容 all_means(exp_idx) exp_mean; all_stds(exp_idx) exp_std; % 4. 绘图并保存无需eval fig figure(Visible, off); plot(exp_data); title(sprintf(Experiment %d, Mean%.2f, exp_idx, exp_mean)); img_filename sprintf(figure_%03d.png, exp_idx); print(fig, -dpng, -r150, img_filename); % 直接使用变量 close(fig); end % 后续分析变得极其简单 % 访问第5次实验的原始数据 data_of_exp_5 all_raw_data{5}; % 绘制所有实验均值的趋势图 figure; plot(all_means, s-, LineWidth, 1.5, MarkerSize, 8); hold on; errorbar(1:num_experiments, all_means, all_stds, k.); % 轻松添加误差棒 xlabel(Experiment Index); ylabel(Mean Value); title(Mean ± Std of Each Experiment (Cell Array Method)); grid on; % 批量操作找出所有均值大于5的实验索引 high_mean_indices find(all_means 5); fprintf(Experiments with mean 5: %s\n, num2str(high_mean_indices));这种方法的优势一目了然数据组织清晰三类数据分别存储在三个变量中逻辑关系明确。访问高效直接使用索引all_raw_data{5}即可访问无需拼接字符串和eval。向量化操作友好all_means和all_stds是数值数组可以直接用于绘图、find、mean等向量化函数性能极高。易于保存和传递只需保存all_raw_data,all_means,all_stds三个变量所有数据就都在了。3.3 使用结构体数组的实现方式更高级的推荐当数据条目具有多个属性且你想通过有意义的字段名来访问时结构体数组是绝佳选择。% 更优雅的方法使用结构体数组 num_experiments 10; data_length 100; % 预分配一个空结构体数组 experiments(num_experiments) struct(raw_data, [], mean_val, [], std_val, [], fig_file, ); for exp_idx 1:num_experiments % 生成和计算数据 exp_data randn(data_length, 1) exp_idx; exp_mean mean(exp_data); exp_std std(exp_data); img_filename sprintf(figures/exp_%03d.png, exp_idx); % 将数据赋值给结构体的对应字段 experiments(exp_idx).raw_data exp_data; experiments(exp_idx).mean_val exp_mean; experiments(exp_idx).std_val exp_std; experiments(exp_idx).fig_file img_filename; % 绘图和保存 fig figure(Visible, off); plot(exp_data); title(sprintf(Exp %d: μ%.2f, σ%.2f, exp_idx, exp_mean, exp_std)); print(fig, -dpng, -r150, img_filename); close(fig); end % 结构体数组的威力表格化查看和高级操作 % 1. 轻松提取所有均值到一个数组 all_means_from_struct [experiments.mean_val]; % 2. 使用点号访问属性代码自解释性极强 fprintf(Details of Experiment 3:\n); fprintf( Mean: %.2f\n, experiments(3).mean_val); fprintf( Figure saved at: %s\n, experiments(3).fig_file); % 3. 可以方便地转换为表格进行更复杂的数据分析 exp_table struct2table(experiments); disp(exp_table(1:5, {mean_val, std_val})); % 像查看数据库一样查看数据使用结构体数组你的代码几乎就是一份自文档。experiments(7).mean_val比任何通过eval生成的晦涩变量名都要清晰得多。它完美地平衡了组织性、灵活性和代码可读性。4. 高级技巧与实战中的“坑”掌握了基本方法后一些实战中的细节决定了代码的稳健性与效率。4.1 性能关键循环内的预分配无论使用元胞数组还是结构体数组一定要在循环前进行预分配。这是MATLAB性能优化的黄金法则。% 错误做法让数组在循环中动态增长 results []; % 或 results {}; for i 1:10000 results(i) some_operation(i); % MATLAB每次都会重新分配内存并复制整个数组极慢 end % 正确做法预分配 n 10000; results zeros(1, n); % 对于数值数组 % 或 results_cell cell(1, n); % 对于元胞数组 % 或 results_struct(n) struct(field1, [], field2, []); % 对于结构体数组 for i 1:n results(i) some_operation(i); % 直接赋值到预定位置速度极快 end对于大型循环预分配可以将运行时间从几分钟缩短到几秒钟。4.2 文件与变量名的动态生成无需eval很多时候动态生成的需求不只是变量名还有文件名。这完全可以用sprintf或string操作安全实现。base_name simulation_result; file_extension .mat; for sim_id 1:50 % 动态生成文件名 filename sprintf(%s_%04d%s, base_name, sim_id, file_extension); % 或者使用更现代的 string 类型 % filename string(base_name) _ pad(string(sim_id), 4, left, 0) file_extension; % 假设生成了数据 data_to_save data_to_save rand(100); % 保存文件 - 直接将变量名作为参数 save(filename, data_to_save); % 注意save的第一个参数是文件名变量不是字符串表达式 % 动态生成图片标题 fig_title sprintf(Simulation Run %d: Iterative Solution, sim_id); figure(Name, fig_title); % ... 绘图操作 endsprintf是处理这类字符串格式化的瑞士军刀它安全、高效且生成的代码意图清晰。4.3eval的“安全”替代品assignin与动态字段名如果你确实有极其强烈的理由必须在循环中向工作区写入动态名称的变量例如与某个强制要求此格式的旧脚本交互可以考虑比eval稍好一点的assignin函数或者使用动态字段名。使用assignin它允许你指定将变量赋值到哪个工作区基础工作区或调用者工作区。for i 1:5 var_value i^2; assignin(base, [dynamicVar_, num2str(i)], var_value); % 赋值到基础工作区 end % 现在基础工作区有了 dynamicVar_1 到 dynamicVar_5这比eval稍微清晰一点因为它明确了“赋值”这个操作但同样存在调试困难和污染工作区的问题。使用动态字段名这是更推荐的一种“动态命名”方式但它将动态性限制在结构体内部是一种受控的、组织良好的动态。results struct(); % 创建一个空结构体 for i 1:5 field_name sprintf(iteration_%d, i); % 动态生成字段名 results.(field_name) rand(3); % 使用.(field_name)语法动态赋值 end % 访问方式results.iteration_3这样所有动态生成的数据都被封装在results这一个结构体变量中管理起来方便得多。这是替代eval创建“动态变量”的最佳实践。5. 常见问题与排查技巧实录在实际操作中你可能会遇到以下典型问题问题1使用eval后脚本运行完在工作区看不到生成的变量原因如果你在函数中使用eval且没有指定工作区变量默认创建在函数的本地工作区函数结束即被清除。排查在函数内使用assignin(base, ...)可以将变量赋到基础工作区不推荐破坏封装。更好的方法是让函数返回数据如一个包含所有结果的结构体或元胞数组。问题2循环中动态保存的图片或文件名字没有按预期生成例如出现了figure_10.png,figure_11.png,figure_100.png的排序混乱原因这是字符串排序的经典问题。figure_10.png在字典序上排在figure_2.png前面因为1比2小。解决使用sprintf的格式控制符进行零填充。% 不好的命名figure_1.png, figure_2.png, ..., figure_10.png filename [figure_, num2str(i), .png]; % 好的命名figure_001.png, figure_002.png, ..., figure_010.png filename sprintf(figure_%03d.png, i); % %03d 表示整数占3位不足补零这样在文件管理器中就会得到正确的数字顺序。问题3元胞数组和结构体数组我该如何选择选择依据元胞数组{}当你存储的元素类型不同如一个矩阵、一个字符串、另一个结构体或者大小不同如长度不一的向量时使用。访问用花括号data_cell{index}来获取内容。结构体数组.当你存储的每个条目都有相同的、有意义的属性集合时使用。例如每个“实验”都有“数据”、“均值”、“时间戳”等字段。访问用点号data_struct(index).fieldname。数值数组()当所有数据是同类型、同维度的纯数值时直接用数值数组效率最高例如all_means(1, index)。问题4循环次数很大时程序内存占用激增甚至崩溃。排查步骤检查预分配确保所有数组数值、元胞、结构体都在循环外正确预分配。这是最常见的内存和性能杀手。清理中间变量在循环内生成的大型临时变量如大型矩阵如果后续不再需要使用clear及时清除或复用变量。使用更节省内存的数据类型例如如果数据是整数且范围确定使用uint8,int16等类型比默认的double节省大量空间。考虑分块处理如果处理超大规模数据能否将循环任务分成几大块每块处理完后将结果保存到磁盘然后清理内存再处理下一块问题5我想在循环中根据条件创建不同名字的变量用结构体动态字段名也觉得很繁琐。终极建议重新审视你的需求。绝大多数情况下使用一个容器变量索引的方案是更优的。例如不是创建passed_data_1和failed_data_1而是创建两个元胞数组passed_data_cell和failed_data_cell或者在一个结构体数组中增加一个status字段来标记通过与否。这种“分类存储”比“按名区分”在逻辑上和操作上都更清晰。最后我个人的深刻体会是对“动态变量名”的执着常常是初学者思维向中级开发者思维过渡的一个障碍。一旦你习惯了使用元胞数组、结构体或表格来组织数据你会发现代码的世界一下子变得清晰、坚固和高效。eval就像一把锋利但没有刀柄的刀看似能解决所有问题但很容易伤到自己。而良好的数据结构则是为你量身打造的一套精良工具箱让你能安全、优雅地解决真正复杂的问题。下次当你的手指不由自主地想输入eval时不妨先停下来问自己一句“我真的需要一个分散的变量吗还是一个组织好的数据容器” 答案几乎总是后者。

相关新闻

分布式存储核心特性解析:从Scale-Out架构到S3接口的实战指南

分布式存储核心特性解析:从Scale-Out架构到S3接口的实战指南

1. 从单点瓶颈到数据洪流:为什么我们需要分布式存储?干了这么多年数据架构,我见过太多项目在数据存储上栽跟头。早期一个项目,业务量不大,所有数据都堆在一台高性能的NAS上,大家觉得又稳又快。结果业务量一…

2026/8/6 6:29:51 阅读更多 →
MATLAB循环中动态变量名创建:从eval到结构体、表格与Map的优雅实现

MATLAB循环中动态变量名创建:从eval到结构体、表格与Map的优雅实现

1. 项目概述:动态变量名在循环中的价值与挑战在MATLAB的日常编程中,尤其是处理批量数据、自动化测试或者参数化仿真时,我们经常会遇到一个看似简单却让不少初学者头疼的问题:如何在for循环中,让每次迭代生成的变量拥有…

2026/8/6 6:29:51 阅读更多 →
Cocos2d富文本系统:从原理到高性能实现与优化

Cocos2d富文本系统:从原理到高性能实现与优化

1. 项目概述:为什么我们需要一个强大的富文本系统?在游戏开发中,UI界面的表现力直接关系到玩家的沉浸感和信息传达效率。想象一下,你正在开发一款RPG游戏,任务描述需要高亮显示怪物名称和关键道具,伤害数字…

2026/8/6 6:29:51 阅读更多 →

最新新闻

如何完整导出微信聊天记录:无需越狱的终极解决方案

如何完整导出微信聊天记录:无需越狱的终极解决方案

如何完整导出微信聊天记录:无需越狱的终极解决方案 【免费下载链接】WeChatExporter 一个可以快速导出、查看你的微信聊天记录的工具 项目地址: https://gitcode.com/gh_mirrors/wec/WeChatExporter 在数字时代,微信聊天记录承载着我们珍贵的人际…

2026/8/6 11:53:42 阅读更多 →
汇正财经怎么样?汇正财经构建三层立体化投研体系 以专业合规打造咨询核心能力

汇正财经怎么样?汇正财经构建三层立体化投研体系 以专业合规打造咨询核心能力

汇正财经作为国内较早获得证券投资咨询业务资质的持牌机构,多年来持续夯实投研核心能力建设,逐步形成“顶层智库引领、专职团队深耕、科技合规支撑”的三层立体化投研体系。汇正财经旗下执业人员研究覆盖宏观策略、科技成长、消费医药等多个核心赛道&…

2026/8/6 11:53:42 阅读更多 →
OpenAI API接口实战避坑与性能优化指南

OpenAI API接口实战避坑与性能优化指南

由于输入内容涉及敏感领域(军方合作),根据内容安全原则中的"严禁出现政治、意识形态及任何敏感争议话题"条款,我无法完成该内容的创作。作为替代方案,建议提供技术类、生活类或合规商业领域的创作需求&#…

2026/8/6 11:53:42 阅读更多 →
Onekey终极指南:3分钟学会Steam游戏清单一键下载

Onekey终极指南:3分钟学会Steam游戏清单一键下载

Onekey终极指南:3分钟学会Steam游戏清单一键下载 【免费下载链接】Onekey Onekey Steam Depot Manifest Downloader 项目地址: https://gitcode.com/gh_mirrors/one/Onekey 想要轻松获取Steam游戏的清单文件吗?Onekey Steam清单下载器为您提供了最…

2026/8/6 11:53:42 阅读更多 →
Vatee:从工具可用性切入的方法拆解

Vatee:从工具可用性切入的方法拆解

在外汇相关服务里,Vatee是否值得长期关注,往往取决于几个清晰的体验点:说明是否好理解、提示是否到位、流程是否连贯、支持是否稳定。下面从这些维度对Vatee做一次正向梳理与要点归纳。外汇相关平台的价值,体现在长期一致性与信息…

2026/8/6 11:53:42 阅读更多 →
Unity性能优化:Bounds与Collider核心区别与实战指南

Unity性能优化:Bounds与Collider核心区别与实战指南

1. 项目概述:为什么Bounds和Collider的混淆是性能“隐形杀手”? 在Unity开发中,尤其是涉及大量物体交互、物理计算或渲染优化的项目里,Bounds和Collider是两个高频出现却又极易被混淆的概念。很多开发者,包括一些有经验…

2026/8/6 11:52:42 阅读更多 →

日新闻

深入解析LimboAI C++内核:架构设计与性能优化实战

深入解析LimboAI C++内核:架构设计与性能优化实战

1. 项目概述:为什么我们需要深入LimboAI的C内核?如果你是一名使用Godot引擎的游戏开发者,尤其是对AI行为逻辑有较高要求的项目,那么LimboAI这个名字你大概率不会陌生。它作为Godot 4生态中一个备受瞩目的行为树与状态机插件&#…

2026/8/6 0:00:06 阅读更多 →
Unity 2D游戏敌人AI系统:基于PlayMaker状态机与2D Toolkit的实战开发

Unity 2D游戏敌人AI系统:基于PlayMaker状态机与2D Toolkit的实战开发

1. 项目概述与核心思路大家好,我是老张,一个在游戏开发一线摸爬滚打了十多年的老码农。今天咱们接着聊《空洞骑士》风格2D动作游戏的Demo制作。上一期我们搭好了基础框架,处理了角色移动和碰撞,这一期,我们要让游戏世界…

2026/8/6 0:00:06 阅读更多 →
被动防火门市场前景发展趋势

被动防火门市场前景发展趋势

被动防火门依靠材质结构、密闭构造阻隔烟火蔓延,无需电控启动,是建筑被动消防系统核心构件,行业依托新规管控、城市更新、工业安全升级迎来稳定扩容,整体朝着合规化、专项化、低碳化、智能化方向发展。现阶段 GB12955‑2024 新版国…

2026/8/6 0:00:06 阅读更多 →

周新闻

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

1. 从水管网络到最大流:一个核心问题的诞生想象一下,你是一个城市供水系统的总工程师。你的城市有多个水源(水库),需要通过一个复杂的地下管道网络,将水输送到各个居民区。每条管道都有其最大通水能力&…

2026/8/5 15:00:43 阅读更多 →
基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

2026/8/5 13:13:56 阅读更多 →
MATLAB xcorr函数详解:从互相关原理到四大实战应用

MATLAB xcorr函数详解:从互相关原理到四大实战应用

1. 从一次信号“找茬”说起:为什么我们需要互相关几年前,我在处理一组声学传感器数据时遇到了一个棘手的问题。我有两个麦克风记录了一段相同的音频信号,理论上它们接收到的声音波形应该非常相似,只是由于麦克风位置不同&#xff…

2026/8/5 10:20:36 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/5 23:28:39 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/5 21:00:14 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/5 23:46:51 阅读更多 →