obj analysis2

GCC工具详解
本文介绍了GCC环境下的几个实用工具:ar、nm和objdump。ar用于库文件操作,nm用于列出目标文件的符号清单,objdump则提供强大的对象文件内容查看功能。通过这些工具,开发者可以更好地理解和控制编译生成的对象文件。
最近由于工作需要,研究了以下gcc环境的相关工具。从wtzmax的专栏上发现了这篇 文章非常不错。 前言 如果普通编程不需要了解这些东西,如果想精确控制你的对象文件的格式或者你想查看一下文件对象里的内容以便作出某种判断,刚你可以看一下下面 的工具:objdump, nm, ar。当然,本文不可能非常详细的说明它们的使用方法和功能。如果你觉得本文不够清楚,你可以使用:man. 我的计划只是想让更多的人了解这些工具,以后在今后 的编程过程中能有所帮助。 操作系统: Linux 开始
  1. 库文件操作命令:ar ----非常好的东东。。让你能查看函数库里的详细情况和用多个对象文件生成一个库文件。
    1. 经常用法:
      1. ar -t libname.a //显示所有对象文件(.o文件)的列表.例: # ar t libtest.a libtest1.o libtest2.o
      2. ar -rv libname.a  objfile1.o objfile2.o ... objfilen.o  //把objfile1.o--objfilen.o打包成一个库文件
    2. ar 选项 d:从库中删除模块。按模块原来的文件名指定要删除的模块。如果使用了任选项v则列出被删除的每个模块。 m:该操作是在一个库中移动成员。当库中如果有若干模块有相同的符号定义(如函数定义),则成员的位置顺序很重要。如果没有指定任选项,任何指定的成员将移到库的最后。也可以使用'a','b',或'I'任选项移动到指定的位置。 p:显示库中指定的成员到标准输出。如果指定任选项v,则在输出成员的内容前,将显示成员的名字。如果没有指定成员的名字,所有库中的文件将显示出来。 q:快速追加。增加新模块到库的结尾处。并不检查是否需要替换。'a','b',或'I'任选项对此操作没有影响,模块总是追加的库的结尾处。如果使用了任选项v则列出每个模块。 这时,库的符号表没有更新,可以用'ar s'或ranlib来更新库的符号表索引。 r:在库中插入模块(替换)。当插入的模块名已经在库中存在,则替换同名的模块。如果若干模块中有一个模块在库中不存在,ar显示一个错误消息,并不替换其他同名模块。默认的情况下,新的成员增加在库的结尾处,可以使用其他任选项来改变增加的位置。 t:显示库的模块表清单。一般只显示模块名。 x:从库中提取一个成员。如果不指定要提取的模块,则提取库中所有的模块。   下面在看看可与操作选项结合使用的任选项: a:在库的一个已经存在的成员后面增加一个新的文件。如果使用任选项a,则应该为命令行中membername参数指定一个已经存在的成员名。 b:在库的一个已经存在的成员前面增加一个新的文件。如果使用任选项b,则应该为命令行中membername参数指定一个已经存在的成员名。 c:创建一个库。不管库是否存在,都将创建。 f:在库中截短指定的名字。缺省情况下,文件名的长度是不受限制的,可以使用此参数将文件名截短,以保证与其它系统的兼容。 i:在库的一个已经存在的成员前面增加一个新的文件。如果使用任选项i,则应该为命令行中membername参数指定一个已经存在的成员名(类似任选项b)。 l:暂未使用 N:与count参数一起使用,在库中有多个相同的文件名时指定提取或输出的个数。 o:当提取成员时,保留成员的原始数据。如果不指定该任选项,则提取出的模块的时间将标为提取出的时间。 P:进行文件名匹配时使用全路径名。ar在创建库时不能使用全路径名(这样的库文件不符合POSIX标准),但是有些工具可以。 s:写入一个目标文件索引到库中,或者更新一个存在的目标文件索引。甚至对于没有任何变化的库也作该动作。对一个库做ar s等同于对该库做ranlib。 S:不创建目标文件索引,这在创建较大的库时能加快时间。 u:一般说来,命令ar r...插入所有列出的文件到库中,如果你只想插入列出文件中那些比库中同名文件新的文件,就可以使用该任选项。该任选项只用于r操作选项。 v:该选项用来显示执行操作选项的附加信息。 V:显示ar的版本.
  2. nm --列出目标文件(.o)的符号清单。。NND,太激动了。刚知道此命令时让我三天没睡好觉。我就使劲用了一把。
    1. 常用法:
      1. nm -s filename.a/filename.o/a.out  里边所有的符号列表一清二楚。例: # nm -s a.out 080495b8 A __bss_start 08048334 t call_gmon_start 080495b8 b completed.5751 080494b8 d __CTOR_END__ 080494b4 d __CTOR_LIST__ 080495ac D __data_start 080495ac W data_start 08048450 t __do_global_ctors_aux 08048360 t __do_global_dtors_aux 080495b0 D __dso_handle 080494c0 d __DTOR_END__ 080494bc d __DTOR_LIST__ 080494c8 d _DYNAMIC 080495b8 A _edata 080495bc A _end 0804847c T _fini 08048498 R _fp_hw 08048390 t frame_dummy 080484b0 r __FRAME_END__ 08049594 d _GLOBAL_OFFSET_TABLE_          w __gmon_start__ 0804844c T __i686.get_pc_thunk.bx 080482b8 T _init 080494b4 a __init_array_end 080494b4 a __init_array_start 0804849c R _IO_stdin_used 080494c4 d __JCR_END__ 080494c4 d __JCR_LIST__          w _Jv_RegisterClasses 080483e0 T __libc_csu_fini 080483f0 T __libc_csu_init          U __libc_start_main@@GLIBC_2.0 080483b4 T main 080495b4 d p.5749          U puts@@GLIBC_2.0 08048310 T _start
    2. 选项/属性: -a或--debug-syms:显示调试符号。 -B:等同于--format=bsd,用来兼容MIPS的nm。 -C或--demangle:将低级符号名解码(demangle)成用户级名字。这样可以使得C++函数名具有可读性。 -D或--dynamic:显示动态符号。该任选项仅对于动态目标(例如特定类型的共享库)有意义。 -f format:使用format格式输出。format可以选取bsd、sysv或posix,该选项在GNU的nm中有用。默认为bsd。 -g或--extern-only:仅显示外部符号。 -n、-v或--numeric-sort:按符号对应地址的顺序排序,而非按符号名的字符顺序。 -p或--no-sort:按目标文件中遇到的符号顺序显示,不排序。 -P或--portability:使用POSIX.2标准输出格式代替默认的输出格式。等同于使用任选项-f posix。 -s或--print-armap:当列出库中成员的符号时,包含索引。索引的内容包含:哪些模块包含哪些名字的映射。 -r或--reverse-sort:反转排序的顺序(例如,升序变为降序)。 --size-sort:按大小排列符号顺序。该大小是按照一个符号的值与它下一个符号的值进行计算的。 -t radix或--radix=radix:使用radix进制显示符号值。radix只能为"d"表示十进制、"o"表示八进制或"x"表示十六进制。 --target=bfdname:指定一个目标代码的格式,而非使用系统的默认格式。 -u或--undefined-only:仅显示没有定义的符号(那些外部符号)。 -l或--line-numbers:对每个符号,使用调试信息来试图找到文件名和行号。对于已定义的符号,查找符号地址的行号。对于未定义符号,查找指向符号重定位入口的行号。如果可以找到行号信息,显示在符号信息之后。 -V或--version:显示nm的版本号。 --help:显示nm的任选项。
  3. objdump  文件命令功能强的惊人。能实现上述两个命令(ar,nm)的很多功能。它主要是查看对象文件的内容信息。
    1. 常用法:
      1. objdump -h file<.o,.a,.out>//查看对象文件所有的节sections.例如: # objdump -h libtest1.o libtest1.o:     file format elf32-i386 Sections: Idx Name          Size      VMA       LMA       File off  Algn   0 .text         00000014  00000000  00000000  00000034  2**2                   CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE   1 .data         00000000  00000000  00000000  00000048  2**2                   CONTENTS, ALLOC, LOAD, DATA   2 .bss          00000000  00000000  00000000  00000048  2**2                   ALLOC   3 .rodata       0000000e  00000000  00000000  00000048  2**0                   CONTENTS, ALLOC, LOAD, READONLY, DATA   4 .comment      0000001f  00000000  00000000  00000056  2**0                   CONTENTS, READONLY   5 .note.GNU-stack 00000000  00000000  00000000  00000075  2**0                   CONTENTS, READONLY
      2. objdump -t 查看对象文件所有的符号列表,相当于 nm -s objfilename,如: # objdump -t libtest1.o libtest1.o:     file format elf32-i386 SYMBOL TABLE: 00000000 l    df *ABS*  00000000 libtest1.c 00000000 l    d  .text  00000000 .text 00000000 l    d  .data  00000000 .data 00000000 l    d  .bss   00000000 .bss 00000000 l    d  .rodata        00000000 .rodata 00000000 l    d  .note.GNU-stack        00000000 .note.GNU-stack 00000000 l    d  .comment       00000000 .comment 00000000 g     F .text  00000014 print_test1 00000000         *UND*  00000000 puts
    2. 更多信息请查看选项: --archive-headers -a 显示档案库的成员信息,与 ar tv 类似     objdump -a libpcap.a     和 ar -tv libpcap.a 显示结果比较比较     显然这个选项没有什么意思。 --adjust-vma=offset     When  dumping  information, first add offset to all     the section addresses.  This is useful if the  sec-     tion  addresses  do  not correspond  to the symbol     table, which can happen when  putting  sections  at     particular  addresses when using a format which can     not represent section addresses, such as a.out. -b bfdname --target=bfdname     指定目标码格式。这不是必须的,objdump能自动识别许多格式,     比如:objdump -b oasys -m vax -h fu.o     显示fu.o的头部摘要信息,明确指出该文件是Vax系统下用Oasys     编译器生成的目标文件。objdump -i将给出这里可以指定的     目标码格式列表 --demangle -C 将底层的符号名解码成用户级名字,除了去掉所有开头    的下划线之外,还使得C++函数名以可理解的方式显示出来。 --debugging     显示调试信息。企图解析保存在文件中的调试信息并以C语言     的语法显示出来。仅仅支持某些类型的调试信息。 --disassemble -d 反汇编那些应该还有指令机器码的section --disassemble-all -D 与 -d 类似,但反汇编所有section --prefix-addresses     反汇编的时候,显示每一行的完整地址。这是一种比较老的反汇编格式。     显示效果并不理想,但可能会用到其中的某些显示,自己可以对比。 --disassemble-zeroes     一般反汇编输出将省略大块的零,该选项使得这些零块也被反汇编。 -EB -EL --endian={big|little}     这个选项将影响反汇编出来的指令。     little-endian就是我们当年在dos下玩汇编的时候常说的高位在高地址,     x86都是这种。 --file-headers -f 显示objfile中每个文件的整体头部摘要信息。 --section-headers --headers -h 显示目标文件各个section的头部摘要信息。 --help 简短的帮助信息。 --info -i 显示对于 -b 或者 -m 选项可用的架构和目标格式列表。 --section=name -j name 仅仅显示指定section的信息 --line-numbers -l 用文件名和行号标注相应的目标代码,仅仅和-d、-D或者-r一起使用    使用-ld和使用-d的区别不是很大,在源码级调试的时候有用,要求    编译时使用了-g之类的调试编译选项。 --architecture=machine -m machine     指定反汇编目标文件时使用的架构,当待反汇编文件本身没有描述     架构信息的时候(比如S-records),这个选项很有用。可以用-i选项     列出这里能够指定的架构 --reloc -r 显示文件的重定位入口。如果和-d或者-D一起使用,重定位部分以反汇    编后的格式显示出来。 --dynamic-reloc -R 显示文件的动态重定位入口,仅仅对于动态目标文件有意义,比如某些    共享库。 --full-contents -s 显示指定section的完整内容。     objdump --section=.text -s inet.o | more --source -S 尽可能反汇编出源代码,尤其当编译的时候指定了-g这种调试参数时,    效果比较明显。隐含了-d参数。 --show-raw-insn     反汇编的时候,显示每条汇编指令对应的机器码,除非指定了     --prefix-addresses,这将是缺省选项。 --no-show-raw-insn     反汇编时,不显示汇编指令的机器码,这是指定 --prefix-addresses     选项时的缺省设置。 --stabs     Display the contents of the .stab, .stab.index, and     .stab.excl sections from an ELF file.  This is only     useful  on  systems  (such as Solaris 2.0) in which     .stab debugging symbol-table entries are carried in     an ELF section.  In most other file formats, debug-     ging  symbol-table  entries  are interleaved  with     linkage symbols, and are visible in the --syms output. --start-address=address     从指定地址开始显示数据,该选项影响-d、-r和-s选项的输出。 --stop-address=address     显示数据直到指定地址为止,该选项影响-d、-r和-s选项的输出。 --syms -t 显示文件的符号表入口。类似于nm -s提供的信息 --dynamic-syms -T 显示文件的动态符号表入口,仅仅对动态目标文件有意义,比如某些    共享库。它显示的信息类似于 nm -D|--dynamic 显示的信息。 --version 版本信息     objdump --version --all-headers -x 显示所有可用的头信息,包括符号表、重定位入口。-x 等价于    -a -f -h -r -t 同时指定。     objdump -x inet.o
优化一下下面的代码,给我优化后的完整的代码:classdef TDMPerformanceAnalyzer < TDMSystem properties analysisResults % 分析结果结构体 snrRange % SNR测试范围 slotRange % 时隙数量测试范围 iterationData % 迭代分析数据 comparisonData % 比较分析数据 efficiencyData % 效率分析数据 summaryTable % 汇总结果表格 end methods function obj = TDMPerformanceAnalyzer(params) % 构造函数 - 验证和初始化参数 if ~isstruct(params) error('输入参数必须是结构体'); end % 调用父类构造函数 obj@TDMSystem(params); % 初始化分析参数 if ~isfield(params, 'snrRange') % 从其他代码中获取的SNR值 obj.snrRange = [15 25 35]; % 使用前面三个代码中的SNR值 else obj.snrRange = params.snrRange; end if ~isfield(params, 'slotRange') % 从其他代码中获取的时隙值 obj.slotRange = [30 60 90]; % 使用前面三个代码中的时隙值 else obj.slotRange = params.slotRange; end % 初始化结果存储 obj.analysisResults = struct(); obj.iterationData = struct(); obj.comparisonData = struct(); obj.efficiencyData = struct(); obj.summaryTable = table(); end function obj = runPerformanceAnalysis(obj) % 运行全面性能分析 fprintf('开始TDM系统性能分析...\n'); try % 1. 基础性能分析 fprintf('执行基础性能分析...\n'); obj = obj.runBaseAnalysis(); % 2. SNR敏感性分析 fprintf('执行SNR敏感性分析...\n'); obj = obj.runSNRAnalysis(); % 3. 时隙数量分析 fprintf('执行时隙数量分析...\n'); obj = obj.runSlotAnalysis(); % 4. 策略比较分析 fprintf('执行策略比较分析...\n'); obj = obj.runStrategyComparison(); % 5. 效率分析 fprintf('执行系统效率分析...\n'); obj = obj.runEfficiencyAnalysis(); % 6. 生成汇总表格 fprintf('生成性能对比汇总表...\n'); obj = obj.generateSummaryTable(); % 7. 可视化分析结果 fprintf('可视化分析结果...\n'); obj.visualizeAnalysisResults(); % 8. 导出汇总表格 obj.exportSummaryTable(); fprintf('性能分析完成!\n'); catch ME fprintf('分析过程中发生错误: %s\n', ME.message); rethrow(ME); end end function obj = runBaseAnalysis(obj) % 执行基础性能分析 % 复用父类的仿真逻辑 obj = obj.runSimulation(); % 保存基础分析结果 obj.analysisResults.base = struct(); obj.analysisResults.base.ber = obj.ber; obj.analysisResults.base.snr = obj.performance.snr; obj.analysisResults.base.corr = obj.performance.corr; obj.analysisResults.base.slotAllocation = obj.allocatedSlots; obj.analysisResults.base.slotUtilization = sum(obj.allocatedSlots) / obj.params.totalSlots * 100; end function obj = runSNRAnalysis(obj) % 执行SNR敏感性分析 numSignals = obj.params.numSignals; numSNR = length(obj.snrRange); % 预分配结果数组 berResults = zeros(numSignals, numSNR); snrResults = zeros(numSignals, numSNR); corrResults = zeros(numSignals, numSNR); slotUtilization = zeros(numSNR, 1); % 保存当前SNR设置 originalSNR = obj.params.snrDb; % 对每个SNR值执行仿真 for i = 1:numSNR fprintf('SNR分析: %d/%d (SNR = %.1f dB)\n', i, numSNR, obj.snrRange(i)); % 设置当前SNR obj.params.snrDb = obj.snrRange(i); % 运行仿真 obj = obj.runSimulation(); % 保存结果 berResults(:, i) = obj.ber; snrResults(:, i) = obj.performance.snr; corrResults(:, i) = obj.performance.corr; slotUtilization(i) = sum(obj.allocatedSlots) / obj.params.totalSlots * 100; end % 恢复原始SNR设置 obj.params.snrDb = originalSNR; % 保存SNR分析结果 obj.analysisResults.snr = struct(); obj.analysisResults.snr.range = obj.snrRange; obj.analysisResults.snr.ber = berResults; obj.analysisResults.snr.snr = snrResults; obj.analysisResults.snr.corr = corrResults; obj.analysisResults.snr.slotUtilization = slotUtilization; end function obj = runSlotAnalysis(obj) % 执行时隙数量分析 numSignals = obj.params.numSignals; numSlots = length(obj.slotRange); % 预分配结果数组 berResults = zeros(numSignals, numSlots); snrResults = zeros(numSignals, numSlots); corrResults = zeros(numSignals, numSlots); efficiency = zeros(numSlots, 1); slotUtilization = zeros(numSlots, 1); % 保存当前时隙设置 originalSlots = obj.params.totalSlots; % 对每个时隙数量执行仿真 for i = 1:numSlots fprintf('时隙分析: %d/%d (时隙数 = %d)\n', i, numSlots, obj.slotRange(i)); % 设置当前时隙数量 obj.params.totalSlots = obj.slotRange(i); % 运行仿真 obj = obj.runSimulation(); % 保存结果 berResults(:, i) = obj.ber; snrResults(:, i) = obj.performance.snr; corrResults(:, i) = obj.performance.corr; efficiency(i) = sum(obj.performance.snr) / numSignals; slotUtilization(i) = sum(obj.allocatedSlots) / obj.params.totalSlots * 100; end % 恢复原始时隙设置 obj.params.totalSlots = originalSlots; % 保存时隙分析结果 obj.analysisResults.slots = struct(); obj.analysisResults.slots.range = obj.slotRange; obj.analysisResults.slots.ber = berResults; obj.analysisResults.slots.snr = snrResults; obj.analysisResults.slots.corr = corrResults; obj.analysisResults.slots.efficiency = efficiency; obj.analysisResults.slots.slotUtilization = slotUtilization; end function obj = runStrategyComparison(obj) % 执行不同时隙分配策略的比较分析 numSignals = obj.params.numSignals; strategies = {'fixed', 'priority', 'dynamic'}; numStrategies = length(strategies); % 预分配结果数组 berResults = zeros(numSignals, numStrategies); snrResults = zeros(numSignals, numStrategies); corrResults = zeros(numSignals, numStrategies); slotAllocation = zeros(numSignals, numStrategies); efficiency = zeros(numStrategies, 1); slotUtilization = zeros(numStrategies, 1); % 保存当前策略设置 originalStrategy = obj.params.strategy; % 对每个策略执行仿真 for i = 1:numStrategies fprintf('策略比较: %d/%d (策略 = %s)\n', i, numStrategies, strategies{i}); % 设置当前策略 obj.params.strategy = strategies{i}; % 运行仿真 try obj = obj.runSimulation(); % 保存结果 berResults(:, i) = obj.ber; snrResults(:, i) = obj.performance.snr; corrResults(:, i) = obj.performance.corr; slotAllocation(:, i) = obj.allocatedSlots; efficiency(i) = sum(obj.performance.snr) / numSignals; slotUtilization(i) = sum(obj.allocatedSlots) / obj.params.totalSlots * 100; catch ME fprintf('策略 "%s" 仿真失败: %s\n', strategies{i}, ME.message); fprintf('使用默认策略继续分析\n'); % 使用默认策略运行仿真 obj.params.strategy = originalStrategy; obj = obj.runSimulation(); % 保存默认策略结果作为替代 berResults(:, i) = obj.ber; snrResults(:, i) = obj.performance.snr; corrResults(:, i) = obj.performance.corr; slotAllocation(:, i) = obj.allocatedSlots; efficiency(i) = sum(obj.performance.snr) / numSignals; slotUtilization(i) = sum(obj.allocatedSlots) / obj.params.totalSlots * 100; end end % 恢复原始策略设置 obj.params.strategy = originalStrategy; % 保存策略比较结果 obj.analysisResults.strategy = struct(); obj.analysisResults.strategy.names = strategies; obj.analysisResults.strategy.ber = berResults; obj.analysisResults.strategy.snr = snrResults; obj.analysisResults.strategy.corr = corrResults; obj.analysisResults.strategy.slotAllocation = slotAllocation; obj.analysisResults.strategy.efficiency = efficiency; obj.analysisResults.strategy.slotUtilization = slotUtilization; end function obj = runEfficiencyAnalysis(obj) % 执行系统效率分析 numIterations = 10; % 分析迭代次数 numSignals = obj.params.numSignals; % 预分配结果数组 berHistory = zeros(numIterations, numSignals); snrHistory = zeros(numIterations, numSignals); slotAllocationHistory = zeros(numIterations, numSignals); efficiencyHistory = zeros(numIterations, 1); slotUtilizationHistory = zeros(numIterations, 1); % 保存当前SNR设置 originalSNR = obj.params.snrDb; % 逐步降低SNR,分析系统效率 snrStep = originalSNR / (numIterations - 1); for i = 1:numIterations currentSNR = originalSNR - (i-1) * snrStep; fprintf('效率分析: %d/%d (SNR = %.1f dB)\n', i, numIterations, currentSNR); % 设置当前SNR obj.params.snrDb = currentSNR; % 运行仿真 obj = obj.runSimulation(); % 保存结果 berHistory(i, :) = obj.ber; snrHistory(i, :) = obj.performance.snr; slotAllocationHistory(i, :) = obj.allocatedSlots; efficiencyHistory(i) = sum(obj.performance.snr) / numSignals; slotUtilizationHistory(i) = sum(obj.allocatedSlots) / obj.params.totalSlots * 100; end % 恢复原始SNR设置 obj.params.snrDb = originalSNR; % 保存效率分析结果 obj.efficiencyData = struct(); obj.efficiencyData.snr = originalSNR - (0:numIterations-1) * snrStep; obj.efficiencyData.ber = berHistory; obj.efficiencyData.snrValues = snrHistory; obj.efficiencyData.slotAllocation = slotAllocationHistory; obj.efficiencyData.efficiency = efficiencyHistory; obj.efficiencyData.slotUtilization = slotUtilizationHistory; end function obj = generateSummaryTable(obj) % 生成性能对比汇总表 % 1. 基础性能数据 baseData = table(); baseData.Metric = {'平均BER', '平均SNR', '平均相关系数', '时隙利用率'}; baseData.Value = [mean(obj.analysisResults.base.ber); mean(obj.analysisResults.base.snr); mean(obj.analysisResults.base.corr); obj.analysisResults.base.slotUtilization]; baseData.Value = round(baseData.Value, 4); baseData.Type = {'基础性能', '基础性能', '基础性能', '基础性能'}; % 2. SNR分析关键数据 [~, bestSNRIdx] = min(mean(obj.analysisResults.snr.ber)); snrData = table(); snrData.Metric = {'最佳SNR', '对应BER', '对应时隙利用率'}; snrData.Value = [obj.analysisResults.snr.range(bestSNRIdx); mean(obj.analysisResults.snr.ber(:, bestSNRIdx)); obj.analysisResults.snr.slotUtilization(bestSNRIdx)]; snrData.Value = round(snrData.Value, 4); snrData.Type = {'SNR分析', 'SNR分析', 'SNR分析'}; % 3. 时隙分析关键数据 [~, bestSlotIdx] = max(mean(obj.analysisResults.slots.snr)); slotData = table(); slotData.Metric = {'最佳时隙数', '对应平均SNR', '对应时隙利用率'}; slotData.Value = [obj.analysisResults.slots.range(bestSlotIdx); mean(obj.analysisResults.slots.snr(:, bestSlotIdx)); obj.analysisResults.slots.slotUtilization(bestSlotIdx)]; slotData.Value = round(slotData.Value, 4); slotData.Type = {'时隙分析', '时隙分析', '时隙分析'}; % 4. 策略比较数据 strategyData = table(); strategyData.Metric = obj.analysisResults.strategy.names'; strategyData.Value = obj.analysisResults.strategy.efficiency; strategyData.Value = round(strategyData.Value, 4); strategyData.Type = {'策略比较'}; strategyData.Type = repmat(strategyData.Type, height(strategyData), 1); % 5. 效率分析关键数据 [~, bestEffIdx] = max(obj.efficiencyData.efficiency); efficiencyData = table(); efficiencyData.Metric = {'最高效率SNR', '最高系统效率', '对应时隙利用率'}; efficiencyData.Value = [obj.efficiencyData.snr(bestEffIdx); obj.efficiencyData.efficiency(bestEffIdx); obj.efficiencyData.slotUtilization(bestEffIdx)]; efficiencyData.Value = round(efficiencyData.Value, 4); efficiencyData.Type = {'效率分析', '效率分析', '效率分析'}; % 合并所有表格 obj.summaryTable = [baseData; snrData; slotData; strategyData; efficiencyData]; % 添加单位列 units = cell(height(obj.summaryTable), 1); for i = 1:height(obj.summaryTable) switch obj.summaryTable.Metric{i} case {'平均BER', '对应BER'} units{i} = '无单位'; case {'平均SNR', '最佳SNR', '对应平均SNR', '最高效率SNR', '最高系统效率'} units{i} = 'dB'; case {'平均相关系数'} units{i} = '无单位'; case endsWith(obj.summaryTable.Metric{i}, '时隙利用率') units{i} = '%'; case {'最佳时隙数'} units{i} = '个'; otherwise units{i} = 'dB'; end end obj.summaryTable.Properties.VariableNames{2} = '值'; obj.summaryTable.单位 = units; end function visualizeAnalysisResults(obj) % 可视化所有分析结果 % 创建主图窗 mainFig = figure('Name', 'TDM系统性能分析结果', 'Position', [100, 100, 1600, 1200]); % 1. 基础性能指标 subplot(3, 2, 1); bar(obj.analysisResults.base.ber); title('基础误码率 (MSE)'); xlabel('信号编号'); ylabel('MSE'); grid on; xticks(1:length(obj.analysisResults.base.ber)); % 2. SNR敏感性分析 subplot(3, 2, 2); hold on; colors = lines(length(obj.analysisResults.base.ber)); for i = 1:length(obj.analysisResults.base.ber) plot(obj.analysisResults.snr.range, obj.analysisResults.snr.ber(i, :), 'Color', colors(i, :), 'LineWidth', 1.5); end hold off; title('SNR对误码率的影响'); xlabel('SNR (dB)'); ylabel('MSE'); grid on; legend(arrayfun(@(x) sprintf('信号%d', x), 1:length(obj.analysisResults.base.ber), 'UniformOutput', false), 'Location', 'best'); % 3. 时隙数量分析 subplot(3, 2, 3); hold on; for i = 1:length(obj.analysisResults.base.ber) plot(obj.analysisResults.slots.range, obj.analysisResults.slots.snr(i, :), 'Color', colors(i, :), 'LineWidth', 1.5); end hold off; title('时隙数量对SNR的影响'); xlabel('时隙数量'); ylabel('SNR (dB)'); grid on; legend(arrayfun(@(x) sprintf('信号%d', x), 1:length(obj.analysisResults.base.ber), 'UniformOutput', false), 'Location', 'best'); % 4. 策略比较分析 subplot(3, 2, 4); bar(obj.analysisResults.strategy.efficiency); title('不同策略的系统效率比较'); xlabel('分配策略'); ylabel('平均SNR (dB)'); grid on; xticks(1:length(obj.analysisResults.strategy.names)); xticklabels(obj.analysisResults.strategy.names); % 5. 效率分析 subplot(3, 2, 5); plot(obj.efficiencyData.snr, obj.efficiencyData.efficiency, 'LineWidth', 1.5); title('系统效率随SNR变化'); xlabel('SNR (dB)'); ylabel('系统效率 (平均SNR)'); grid on; % 6. 时隙利用率分析 subplot(3, 2, 6); hold on; for i = 1:length(obj.analysisResults.base.ber) plot(obj.analysisResults.slots.range, obj.analysisResults.slots.corr(i, :), 'Color', colors(i, :), 'LineWidth', 1.5); end hold off; title('时隙数量对信号相关性的影响'); xlabel('时隙数量'); ylabel('相关系数'); grid on; legend(arrayfun(@(x) sprintf('信号%d', x), 1:length(obj.analysisResults.base.ber), 'UniformOutput', false), 'Location', 'best'); % 添加整体标题 sgtitle(sprintf('TDM系统性能分析 - %d个信号, %d个时隙, %s策略', ... obj.params.numSignals, obj.params.totalSlots, obj.params.strategy)); % 保存图像 try timestamp = datestr(now, 'yyyymmdd_HHMMSS'); filename = sprintf('tdm_performance_analysis_%s.png', timestamp); saveas(mainFig, filename); fprintf('分析结果图像已保存为 %s\n', filename); catch fprintf('无法保存分析结果图像\n'); end % 创建汇总表格图窗 if ~isempty(obj.summaryTable) tableFig = figure('Name', 'TDM系统性能分析汇总表', 'Position', [100, 100, 800, 600]); uitable('Parent', tableFig, 'Data', obj.summaryTable{:, 2:end}, ... 'ColumnName', obj.summaryTable.Properties.VariableNames(2:end), ... 'RowName', obj.summaryTable.Metric, ... 'Position', [20, 20, 760, 560], ... 'FontSize', 10); title(sprintf('TDM系统性能分析汇总表 - %d个信号, %d个时隙, %s策略', ... obj.params.numSignals, obj.params.totalSlots, obj.params.strategy)); % 保存表格图像 try tableFilename = sprintf('tdm_performance_summary_%s.png', timestamp); saveas(tableFig, tableFilename); fprintf('分析汇总表图像已保存为 %s\n', tableFilename); catch fprintf('无法保存分析汇总表图像\n'); end end end function exportSummaryTable(obj, filename) % 导出汇总表格到CSV文件 if nargin < 2 timestamp = datestr(now, 'yyyymmdd_HHMMSS'); filename = sprintf('tdm_performance_summary_%s.csv', timestamp); end if ~isempty(obj.summaryTable) try writetable(obj.summaryTable, filename); fprintf('分析汇总表已导出到 %s\n', filename); catch fprintf('无法导出分析汇总表\n'); end end end function exportAnalysisResults(obj, filename) % 导出分析结果到MAT文件 if nargin < 2 timestamp = datestr(now, 'yyyymmdd_HHMMSS'); filename = sprintf('tdm_analysis_results_%s.mat', timestamp); end results = struct(); results.params = obj.params; results.analysisResults = obj.analysisResults; results.efficiencyData = obj.efficiencyData; results.summaryTable = obj.summaryTable; save(filename, 'results'); fprintf('分析结果已导出到 %s\n', filename); end end methods (Static) function params = createDefaultAnalysisParams() % 创建默认分析参数 params = TDMSystem.createDefaultParams(); params.snrRange = [15 25 35]; % 使用前面三个代码中的SNR值 params.slotRange = [30 60 90]; % 使用前面三个代码中的时隙值 end end end
06-21
根据以上情况和要求,更改以下代码:classdef TDMPerformanceAnalyzer < TDMSystem properties (Access = private) stabilityHistory % 稳定性分析历史 powerConsumption % 功率消耗 efficiencyHistory % 能效历史 qosScore % QoS分数 end properties (Constant) MODULATION_METHODS = {‘BPSK’, ‘QPSK’, ‘16-QAM’}; MODULATION_EFFICIENCY = [1, 2, 4]; % 频谱效率(bps/Hz) MODULATION_COMPLEXITY = [1, 1.5, 2.5]; % 实现复杂度(相对值) COLORS = {‘#0072BD’, ‘#D95319’, ‘#EDB120’, ‘#7E2F8E’, ‘#77AC30’, ‘#4DBEEE’, ‘#A2142F’}; MARKERS = {‘o’, ‘s’, ‘^’, ‘d’, ‘p’, ‘h’, ‘>’}; LINE_STYLES = {‘-’, ‘–’, ‘-.’, ‘:’}; end methods function obj = TDMPerformanceAnalyzer(params) % 构造函数 obj@TDMSystem(params); obj = obj.initializePerformanceData(); % 修复:正确调用私有方法 end function runPerformanceAnalysis(obj) % 运行TDM系统性能分析 fprintf('初始化TDM系统性能分析...\n'); obj = obj.generateSignals(); % 初始时隙分配 obj = obj.allocateSlots(); % 动态性能分析 fprintf('执行动态性能分析...\n'); obj = obj.dynamicPerformanceAnalysis(); % 稳定性分析 fprintf('执行稳定性分析...\n'); obj = obj.stabilityAnalysis(); % 能效分析 fprintf('执行能效分析...\n'); obj = obj.energyEfficiencyAnalysis(); % 系统整体性能评估 fprintf('执行系统整体性能评估...\n'); obj.overallPerformanceEvaluation(); end function obj = dynamicPerformanceAnalysis(obj) % 动态性能分析 iterations = obj.params.iterations; snr_current = obj.params.snrDb; snr_min = 5; snr_decrease_rate = 2; for iter = 1:iterations fprintf('动态分析迭代 #%d (SNR = %.1f dB)...\n', iter, snr_current); % 更新SNR snr_current = max(snr_min, obj.params.snrDb - (iter-1) * snr_decrease_rate); obj.params.snrDb = snr_current; % 系统处理流程 obj = obj.processSystem(); % 评估性能 obj = obj.evaluatePerformance(); % 自适应时隙分配 obj = obj.adaptiveSlotAllocation(); % 计算QoS分数 qos_targets = [0.01, 0.05, 0.1]; % 默认目标误码率 if isfield(obj.params, 'qosTargets') && length(obj.params.qosTargets) >= obj.params.numSignals qos_targets = obj.params.qosTargets(1:obj.params.numSignals); else qos_targets = repmat(qos_targets(1), 1, obj.params.numSignals); end qos = (1 - obj.ber ./ qos_targets')' * 100; qos(qos < 0) = 0; % 确保分数不为负 if isempty(obj.qosScore) obj.qosScore = qos; else obj.qosScore = [obj.qosScore; qos]; end % 可视化当前迭代结果 obj.visualizeDynamicPerformance(iter, snr_current); end end function obj = stabilityAnalysis(obj) % 稳定性分析 clock_drift_max = 0.01; iterations = obj.params.iterations; clock_drift = linspace(0, clock_drift_max, iterations); for iter = 1:iterations fprintf('稳定性分析迭代 #%d (时钟漂移 = %.6f)...\n', iter, clock_drift(iter)); % 更新时钟漂移 obj.params.clockDrift = [0, clock_drift(iter), -clock_drift(iter)]; % 系统处理流程 obj = obj.processSystem(); % 评估性能 obj = obj.evaluatePerformance(); % 记录稳定性分析结果 obj.stabilityHistory = [obj.stabilityHistory; obj.ber']; end % 可视化稳定性分析结果 obj.visualizeStabilityAnalysis(iterations, clock_drift); end function obj = energyEfficiencyAnalysis(obj) % 能效分析 iterations = obj.params.iterations; snr_current = obj.params.snrDb; snr_min = 5; snr_decrease_rate = 2; power_scaling = 0.1; obj.powerConsumption = zeros(iterations, length(obj.MODULATION_METHODS)); obj.efficiencyHistory = zeros(iterations, length(obj.MODULATION_METHODS)); for iter = 1:iterations fprintf('能效分析迭代 #%d (SNR = %.1f dB)...\n', iter, snr_current); % 更新SNR snr_current = max(snr_min, obj.params.snrDb - (iter-1) * snr_decrease_rate); for mod_idx = 1:length(obj.MODULATION_METHODS) % 计算功率消耗 power = obj.calculatePowerConsumption(snr_current, snr_min, ... obj.MODULATION_EFFICIENCY(mod_idx), ... obj.MODULATION_COMPLEXITY(mod_idx), power_scaling); obj.powerConsumption(iter, mod_idx) = power; % 计算能效 efficiency = obj.MODULATION_EFFICIENCY(mod_idx) / power; obj.efficiencyHistory(iter, mod_idx) = efficiency; end end % 可视化能效分析结果 obj.visualizeEnergyEfficiency(iterations); end function visualizeDynamicPerformance(obj, iter, snr) % 可视化动态性能分析结果 fig = figure('Name', ['动态性能分析迭代 #', num2str(iter)], 'Position', [100, 100, 1200, 800]); t = 0:1/obj.params.fs:obj.params.duration-1/obj.params.fs; % 优化布局 gs = tiledlayout(2, 2); gs.Padding = 'compact'; gs.TileSpacing = 'compact'; % 1. 时隙分配 nexttile; b = bar(obj.allocatedSlots); b.FaceColor = obj.COLORS{1}; b.EdgeColor = 'none'; b.LineWidth = 1.5; title(['第' num2str(iter) '次时隙分配 (SNR = ' num2str(snr) 'dB)'], 'FontSize', 12, 'FontWeight', 'bold'); xlabel('信号编号', 'FontSize', 10); ylabel('分配时隙数', 'FontSize', 10); grid on; grid minor; ylim([0, max(obj.allocatedSlots)*1.2]); set(gca, 'FontSize', 10, 'Box', 'on', 'LineWidth', 1.2); % 添加数据标签 for i = 1:length(obj.allocatedSlots) text(i, obj.allocatedSlots(i) + max(obj.allocatedSlots)*0.03, ... num2str(obj.allocatedSlots(i)), ... 'HorizontalAlignment', 'center', 'FontSize', 9, 'FontWeight', 'bold'); end % 2. TDM信号 nexttile; plot(t, obj.tdmSignal, 'Color', obj.COLORS{2}, 'LineWidth', 1.5); title(['第' num2str(iter) '次迭代生成的TDM信号'], 'FontSize', 12, 'FontWeight', 'bold'); xlabel('时间 (s)', 'FontSize', 10); ylabel('幅度', 'FontSize', 10); grid on; grid minor; ylim([-2, 2]); xlim([0, min(0.1, obj.params.duration)]); % 只显示前0.1秒或更短的信号 set(gca, 'FontSize', 10, 'Box', 'on', 'LineWidth', 1.2); % 3. 误码率 nexttile; plot(1:obj.params.numSignals, obj.ber, 'o-', 'LineWidth', 1.5, 'MarkerSize', 8, ... 'MarkerFaceColor', obj.COLORS{3}, 'Color', obj.COLORS{3}); title('估计误码率 (BER)', 'FontSize', 12, 'FontWeight', 'bold'); xlabel('信号编号', 'FontSize', 10); ylabel('误码率', 'FontSize', 10); grid on; grid minor; set(gca, 'YScale', 'log', 'FontSize', 10, 'Box', 'on', 'LineWidth', 1.2); ylim([1e-6, 1]); % 4. QoS分数 nexttile; if ~isempty(obj.qosScore) && size(obj.qosScore, 2) >= obj.params.numSignals % 确保显示最新的QoS分数 latest_qos = obj.qosScore(end, 1:obj.params.numSignals); % 检查是否有NaN或Inf值 valid_indices = ~isnan(latest_qos) & ~isinf(latest_qos); if any(valid_indices) % 只显示有效值 b = bar(1:obj.params.numSignals, latest_qos); b.FaceColor = obj.COLORS{4}; b.EdgeColor = 'none'; b.LineWidth = 1.5; title('服务质量 (QoS) 分数', 'FontSize', 12, 'FontWeight', 'bold'); xlabel('信号编号', 'FontSize', 10); ylabel('QoS分数 (%)', 'FontSize', 10); grid on; grid minor; ylim([0, 110]); set(gca, 'FontSize', 10, 'Box', 'on', 'LineWidth', 1.2); % 添加数据标签 for i = 1:obj.params.numSignals if valid_indices(i) text(i, latest_qos(i) + 3, sprintf('%.1f%%', latest_qos(i)), ... 'HorizontalAlignment', 'center', 'FontSize', 9, 'FontWeight', 'bold'); end end else % 如果没有有效值,显示提示 text(0.5, 0.5, '无有效QoS数据', 'HorizontalAlignment', 'center', 'FontSize', 12); title('服务质量 (QoS) 分数'); axis off; end else % 如果数据为空或维度不匹配,显示提示 text(0.5, 0.5, '未计算QoS分数', 'HorizontalAlignment', 'center', 'FontSize', 12); title('服务质量 (QoS) 分数'); axis off; end % 添加水印 annotation(fig, 'textbox', [0.7, 0.01, 0.25, 0.05], 'String', ['迭代: ' num2str(iter)], ... 'EdgeColor', 'none', 'HorizontalAlignment', 'right', 'FontSize', 8); % 优化图形外观 set(fig, 'Color', 'white'); set(gcf, 'PaperPositionMode', 'auto'); end function visualizeStabilityAnalysis(obj, iterations, clock_drift) % 可视化稳定性分析结果 fig = figure('Name', '稳定性分析结果', 'Position', [100, 100, 1200, 800]); % 优化布局 gs = tiledlayout(2, 1); gs.Padding = 'compact'; gs.TileSpacing = 'compact'; % 1. 时钟偏差 nexttile; p = plot(1:iterations, clock_drift, '-o', 'LineWidth', 1.5, 'MarkerSize', 8, ... 'MarkerFaceColor', obj.COLORS{1}, 'Color', obj.COLORS{1}); title('时钟偏差模拟', 'FontSize', 12, 'FontWeight', 'bold'); xlabel('迭代次数', 'FontSize', 10); ylabel('时钟偏差(秒)', 'FontSize', 10); grid on; grid minor; set(gca, 'FontSize', 10, 'Box', 'on', 'LineWidth', 1.2); % 2. 误码率随时钟偏差变化 nexttile; for i = 1:obj.params.numSignals color_idx = mod(i-1, length(obj.COLORS)) + 1; line_idx = mod(i-1, length(obj.LINE_STYLES)) + 1; marker_idx = mod(i-1, length(obj.MARKERS)) + 1; plot(1:iterations, obj.stabilityHistory(:, i), ... 'LineWidth', 1.5, 'Color', obj.COLORS{color_idx}, ... 'Marker', obj.MARKERS{marker_idx}, 'MarkerSize', 6, ... 'LineStyle', obj.LINE_STYLES{line_idx}); hold on; end hold off; title('误码率随时钟偏差变化', 'FontSize', 12, 'FontWeight', 'bold'); xlabel('迭代次数', 'FontSize', 10); ylabel('误码率 (BER)', 'FontSize', 10); legend(arrayfun(@(x) ['信号' num2str(x)], 1:obj.params.numSignals, 'UniformOutput', false), ... 'Location', 'best', 'FontSize', 9); grid on; grid minor; set(gca, 'YScale', 'log', 'FontSize', 10, 'Box', 'on', 'LineWidth', 1.2); ylim([1e-6, 1]); % 添加水印 annotation(fig, 'textbox', [0.7, 0.01, 0.25, 0.05], ... 'String', ['时钟漂移范围: 0 - ' num2str(clock_drift(end))], ... 'EdgeColor', 'none', 'HorizontalAlignment', 'right', 'FontSize', 8); % 优化图形外观 set(fig, 'Color', 'white'); set(gcf, 'PaperPositionMode', 'auto'); end function visualizeEnergyEfficiency(obj, iterations) % 可视化能效分析结果 fig = figure('Name', '能效分析结果', 'Position', [100, 100, 1200, 800]); % 优化布局 gs = tiledlayout(2, 1); gs.Padding = 'compact'; gs.TileSpacing = 'compact'; % 1. 功率消耗 nexttile; for i = 1:length(obj.MODULATION_METHODS) color_idx = mod(i-1, length(obj.COLORS)) + 1; line_idx = mod(i-1, length(obj.LINE_STYLES)) + 1; marker_idx = mod(i-1, length(obj.MARKERS)) + 1; plot(1:iterations, obj.powerConsumption(:, i), ... 'LineWidth', 1.5, 'Color', obj.COLORS{color_idx}, ... 'Marker', obj.MARKERS{marker_idx}, 'MarkerSize', 6, ... 'LineStyle', obj.LINE_STYLES{line_idx}); hold on; end hold off; title('功率消耗随迭代变化', 'FontSize', 12, 'FontWeight', 'bold'); xlabel('迭代次数', 'FontSize', 10); ylabel('功率消耗', 'FontSize', 10); legend(obj.MODULATION_METHODS, 'Location', 'best', 'FontSize', 9); grid on; grid minor; set(gca, 'FontSize', 10, 'Box', 'on', 'LineWidth', 1.2); % 2. 能效 nexttile; for i = 1:length(obj.MODULATION_METHODS) color_idx = mod(i-1, length(obj.COLORS)) + 1; line_idx = mod(i-1, length(obj.LINE_STYLES)) + 1; marker_idx = mod(i-1, length(obj.MARKERS)) + 1; plot(1:iterations, obj.efficiencyHistory(:, i), ... 'LineWidth', 1.5, 'Color', obj.COLORS{color_idx}, ... 'Marker', obj.MARKERS{marker_idx}, 'MarkerSize', 6, ... 'LineStyle', obj.LINE_STYLES{line_idx}); hold on; end hold off; title('能效随迭代变化', 'FontSize', 12, 'FontWeight', 'bold'); xlabel('迭代次数', 'FontSize', 10); ylabel('能效 (bps/Hz/W)', 'FontSize', 10); legend(obj.MODULATION_METHODS, 'Location', 'best', 'FontSize', 9); grid on; grid minor; set(gca, 'FontSize', 10, 'Box', 'on', 'LineWidth', 1.2); % 添加水印 annotation(fig, 'textbox', [0.7, 0.01, 0.25, 0.05], ... 'String', ['调制方式: ' strjoin(obj.MODULATION_METHODS, ', ')], ... 'EdgeColor', 'none', 'HorizontalAlignment', 'right', 'FontSize', 8); % 优化图形外观 set(fig, 'Color', 'white'); set(gcf, 'PaperPositionMode', 'auto'); end function overallPerformanceEvaluation(obj) % 系统整体性能评估 fig = figure('Name', '系统整体性能评估', 'Position', [100, 100, 1200, 1000]); % 计算平均能效 avg_efficiency = mean(obj.efficiencyHistory, 2); % 优化布局 gs = tiledlayout(4, 1); gs.Padding = 'compact'; gs.TileSpacing = 'compact'; % 1. SNR变化 nexttile; snr_values = obj.params.snrDb - (0:obj.params.iterations-1) * 2; snr_values = max(5, snr_values); p = plot(1:obj.params.iterations, snr_values, '-o', 'LineWidth', 1.5, 'MarkerSize', 8, ... 'MarkerFaceColor', obj.COLORS{1}, 'Color', obj.COLORS{1}); title('信噪比 (SNR) 变化', 'FontSize', 12, 'FontWeight', 'bold'); xlabel('迭代次数', 'FontSize', 10); ylabel('SNR (dB)', 'FontSize', 10); grid on; grid minor; set(gca, 'FontSize', 10, 'Box', 'on', 'LineWidth', 1.2); % 2. QoS分数 nexttile; if ~isempty(obj.qosScore) for i = 1:obj.params.numSignals color_idx = mod(i-1, length(obj.COLORS)) + 1; line_idx = mod(i-1, length(obj.LINE_STYLES)) + 1; marker_idx = mod(i-1, length(obj.MARKERS)) + 1; plot(1:size(obj.qosScore, 1), obj.qosScore(:, i), ... 'LineWidth', 1.5, 'Color', obj.COLORS{color_idx}, ... 'Marker', obj.MARKERS{marker_idx}, 'MarkerSize', 6, ... 'LineStyle', obj.LINE_STYLES{line_idx}); hold on; end hold off; title('系统服务质量 (QoS) 分数', 'FontSize', 12, 'FontWeight', 'bold'); xlabel('迭代次数', 'FontSize', 10); ylabel('QoS分数', 'FontSize', 10); legend(arrayfun(@(x) ['信号' num2str(x)], 1:obj.params.numSignals, 'UniformOutput', false), ... 'Location', 'best', 'FontSize', 9); grid on; grid minor; set(gca, 'FontSize', 10, 'Box', 'on', 'LineWidth', 1.2); else text(0.5, 0.5, '未计算QoS分数', 'HorizontalAlignment', 'center', 'FontSize', 12); title('系统服务质量 (QoS) 分数'); axis off; end % 3. 平均能效 nexttile; p = plot(1:obj.params.iterations, avg_efficiency, '-o', 'LineWidth', 1.5, 'MarkerSize', 8, ... 'MarkerFaceColor', obj.COLORS{3}, 'Color', obj.COLORS{3}); title('系统平均能效', 'FontSize', 12, 'FontWeight', 'bold'); xlabel('迭代次数', 'FontSize', 10); ylabel('平均能效 (bps/Hz/W)', 'FontSize', 10); grid on; grid minor; set(gca, 'FontSize', 10, 'Box', 'on', 'LineWidth', 1.2); % 4. 稳定性分析结果 nexttile; if ~isempty(obj.stabilityHistory) for i = 1:obj.params.numSignals color_idx = mod(i-1, length(obj.COLORS)) + 1; line_idx = mod(i-1, length(obj.LINE_STYLES)) + 1; marker_idx = mod(i-1, length(obj.MARKERS)) + 1; plot(1:size(obj.stabilityHistory, 1), obj.stabilityHistory(:, i), ... 'LineWidth', 1.5, 'Color', obj.COLORS{color_idx}, ... 'Marker', obj.MARKERS{marker_idx}, 'MarkerSize', 6, ... 'LineStyle', obj.LINE_STYLES{line_idx}); hold on; end hold off; title('系统稳定性分析结果', 'FontSize', 12, 'FontWeight', 'bold'); xlabel('迭代次数', 'FontSize', 10); ylabel('误码率 (BER)', 'FontSize', 10); legend(arrayfun(@(x) ['信号' num2str(x)], 1:obj.params.numSignals, 'UniformOutput', false), ... 'Location', 'best', 'FontSize', 9); grid on; grid minor; set(gca, 'YScale', 'log', 'FontSize', 10, 'Box', 'on', 'LineWidth', 1.2); ylim([1e-6, 1]); else text(0.5, 0.5, '未执行稳定性分析', 'HorizontalAlignment', 'center', 'FontSize', 12); title('系统稳定性分析结果'); axis off; end % 打印系统性能评估结果 fprintf('===== 系统整体性能评估 =====\n'); fprintf('总迭代次数: %d\n', obj.params.iterations); fprintf('初始信噪比: %.1f dB\n', obj.params.snrDb); fprintf('最终信噪比: %.1f dB\n', snr_values(end)); fprintf('\n'); % 确保avg_qos的大小与numSignals匹配 if ~isempty(obj.qosScore) avg_qos = mean(obj.qosScore, 1); % 检查avg_qos的长度是否与numSignals一致 if length(avg_qos) < obj.params.numSignals % 如果不一致,填充默认值或调整 avg_qos = [avg_qos, zeros(1, obj.params.numSignals - length(avg_qos))]; end fprintf('平均服务质量 (QoS):\n'); for i = 1:obj.params.numSignals fprintf(' 信号%d: %.1f%%\n', i, avg_qos(i)); end fprintf('\n'); end fprintf('能效分析结果:\n'); for mod_idx = 1:length(obj.MODULATION_METHODS) avg_mod_efficiency = mean(obj.efficiencyHistory(:, mod_idx)); fprintf(' %s: 平均能效 = %.3f bps/Hz/W\n', obj.MODULATION_METHODS{mod_idx}, avg_mod_efficiency); end % 保存评估结果 if isprop(obj.params, 'saveResults') && obj.params.saveResults saveResults(obj, snr_values, avg_qos, avg_efficiency); end % 优化图形外观 set(fig, 'Color', 'white'); set(gcf, 'PaperPositionMode', 'auto'); end function obj = adaptiveSlotAllocation(obj) % 自适应时隙分配 % 根据当前误码率调整各信号的时隙分配 % 基本分配比例 baseAllocation = ones(1, obj.params.numSignals) / obj.params.numSignals; % 如果有误码率数据,根据误码率调整分配 if ~isempty(obj.ber) % 误码率倒数作为优先级指标(误码率越高,优先级越高) priority = 1 ./ (obj.ber + 1e-10); % 避免除零错误 % 归一化优先级 priority = priority / sum(priority); % 结合基本分配和优先级 allocation = 0.7 * baseAllocation + 0.3 * priority'; % 确保总分配时隙数不变 allocation = allocation * sum(obj.allocatedSlots); % 转换为整数 obj.allocatedSlots = round(allocation); % 处理舍入误差 diff = sum(obj.allocatedSlots) - sum(allocation); if diff ~= 0 % 找到最大差异的信号进行调整 [~, idx] = max(abs(obj.allocatedSlots - allocation)); obj.allocatedSlots(idx) = obj.allocatedSlots(idx) - diff; end end fprintf('时隙分配调整为: [%s]\n', num2str(obj.allocatedSlots)); end end methods (Access = private) function obj = initializePerformanceData(obj) % 初始化性能数据存储 obj.stabilityHistory = []; obj.powerConsumption = []; obj.efficiencyHistory = []; obj.qosScore = []; end function obj = processSystem(obj) % 系统处理流程 obj = obj.multiplex(); obj = obj.transmit(); obj = obj.demultiplex(); obj = obj.synchronize(); end function power = calculatePowerConsumption(obj, snr, snr_min, efficiency, complexity, scaling) % 功率消耗模型:与SNR、调制效率和复杂度相关 snr_factor = 1 + (snr - snr_min) / (20 - snr_min); efficiency_factor = 1 / efficiency; complexity_factor = complexity; power = scaling * snr_factor * efficiency_factor * complexity_factor; end end methods (Static) function saveResults(obj, snr_values, avg_qos, avg_efficiency) % 保存分析结果到文件 timestamp = datestr(now, 'yyyymmdd_HHMMSS'); filename = ['TDM_Analysis_Results_' timestamp '.mat']; % 保存所有性能数据 save(filename, 'obj', 'snr_values', 'avg_qos', 'avg_efficiency'); fprintf('分析结果已保存到: %s\n', filename); end end end
06-21
优化代码,仅解决性能分析图表没有显示的问题,代码:classdef TDMPerformanceAnalyzer < TDMSystem % TDMPERFORMANCEANALYZER TDM系统性能分析工具 % 继承自TDMSystem基类,提供全面的性能分析功能 properties snrRange % SNR测试范围 (dB) performanceCurves % 性能曲线数据结构 detailedMetrics % 详细性能指标 convergenceAnalysis % 收敛性分析结果 modulationAnalysis % 调制方式对比分析 end properties (Access = private) originalParams % 原始参数备份 end methods function obj = TDMPerformanceAnalyzer(params) % 构造函数 % 输入: params - 系统参数结构体 % 调用父类构造函数 obj = obj@TDMSystem(params); % 备份原始参数 obj.originalParams = params; % 设置默认SNR范围 obj.snrRange = 0:2:20; % 0dB到20dB,步长2dB end function obj = runPerformanceAnalysis(obj, customSNR) % 主性能分析方法 % 输入: customSNR - (可选)自定义SNR范围 % 处理可选参数 if nargin > 1 && ~isempty(customSNR) validateattributes(customSNR, {'numeric'}, {'vector', 'nonempty'}, ... 'runPerformanceAnalysis', 'customSNR'); obj.snrRange = customSNR; end try % 初始化性能数据结构 numSignals = obj.params.numSignals; numSNR = length(obj.snrRange); % 预分配内存 obj.performanceCurves = struct(... 'ber', zeros(numSNR, numSignals), ... 'snr', zeros(numSNR, numSignals), ... 'mse', zeros(numSNR, numSignals), ... 'throughput', zeros(numSNR, numSignals)); % 保存原始SNR设置 originalSNR = obj.params.snrDb; % 进度条显示 hWaitbar = waitbar(0, '正在执行性能分析...', ... 'Name', 'TDM性能分析', ... 'CreateCancelBtn', 'setappdata(gcbf,''canceling'',1)'); setappdata(hWaitbar, 'canceling', 0); % 遍历不同SNR值 for snrIdx = 1:numSNR % 检查取消操作 if getappdata(hWaitbar, 'canceling') break; end % 更新SNR参数 obj.params.snrDb = obj.snrRange(snrIdx); % 调用超类方法 - 使用正确的语法 obj = runSimulation(obj); % 存储性能指标 obj.performanceCurves.ber(snrIdx, :) = obj.performance.ber; obj.performanceCurves.snr(snrIdx, :) = obj.performance.snr; obj.performanceCurves.mse(snrIdx, :) = obj.performance.mse; % 计算吞吐量 (1 - BER) obj.performanceCurves.throughput(snrIdx, :) = 1 - obj.performance.ber; % 更新进度条 waitbar(snrIdx/numSNR, hWaitbar, ... sprintf('正在分析 SNR=%.1f dB (%.0f%%)', ... obj.snrRange(snrIdx), snrIdx/numSNR*100)); end % 关闭进度条 delete(hWaitbar); % 恢复原始SNR obj.params.snrDb = originalSNR; % 执行详细分析 obj = obj.performDetailedAnalysis(); obj = obj.performConvergenceAnalysis(); obj = obj.analyzeModulationImpact(); catch ME % 错误处理 if exist('hWaitbar', 'var') && ishandle(hWaitbar) delete(hWaitbar); end rethrow(ME); end end function obj = set.snrRange(obj, range) % SNR范围设置验证 validateattributes(range, {'numeric'}, {'vector', 'increasing', 'nonnegative'}, ... 'TDMPerformanceAnalyzer', 'snrRange'); obj.snrRange = range; end function obj = performDetailedAnalysis(obj) % 详细性能指标计算 numSignals = obj.params.numSignals; numSNR = length(obj.snrRange); % 初始化结构体 obj.detailedMetrics = struct(... 'avgBER', zeros(1, numSignals), ... 'avgSNR', zeros(1, numSignals), ... 'minBER', zeros(1, numSignals), ... 'maxThroughput', zeros(1, numSignals), ... 'snrSensitivity', zeros(1, numSignals), ... 'berAt10dB', zeros(1, numSignals), ... 'berAt20dB', zeros(1, numSignals)); for i = 1:numSignals % 提取当前信号的性能数据 berData = obj.performanceCurves.ber(:, i); snrData = obj.performanceCurves.snr(:, i); throughputData = obj.performanceCurves.throughput(:, i); % 平均BER和SNR obj.detailedMetrics.avgBER(i) = mean(berData); obj.detailedMetrics.avgSNR(i) = mean(snrData); % 最低BER obj.detailedMetrics.minBER(i) = min(berData); % 最大吞吐量 obj.detailedMetrics.maxThroughput(i) = max(throughputData); % SNR敏感性 (BER改善率) berDiff = diff(berData); snrDiff = diff(obj.snrRange'); obj.detailedMetrics.snrSensitivity(i) = mean(berDiff ./ snrDiff); % 特定SNR点的BER值 idx10dB = find(obj.snrRange >= 10, 1, 'first'); idx20dB = find(obj.snrRange >= 20, 1, 'first'); if ~isempty(idx10dB) obj.detailedMetrics.berAt10dB(i) = berData(idx10dB); end if ~isempty(idx20dB) && idx20dB <= numSNR obj.detailedMetrics.berAt20dB(i) = berData(idx20dB); end end end function obj = performConvergenceAnalysis(obj, threshold) % 收敛性分析 % 输入: threshold - (可选)收敛判断阈值 if nargin < 2 || isempty(threshold) threshold = 1e-4; % 默认收敛判断阈值 end numSignals = obj.params.numSignals; obj.convergenceAnalysis = struct(... 'convergencePoint', zeros(1, numSignals), ... 'stableBER', zeros(1, numSignals), ... 'convergenceSNR', zeros(1, numSignals)); for i = 1:numSignals berValues = obj.performanceCurves.ber(:, i); % 找到BER变化小于阈值的点 berDiff = abs(diff(berValues)); convergenceIdx = find(berDiff < threshold, 1, 'first'); if isempty(convergenceIdx) obj.convergenceAnalysis.convergencePoint(i) = length(obj.snrRange); obj.convergenceAnalysis.stableBER(i) = berValues(end); obj.convergenceAnalysis.convergenceSNR(i) = obj.snrRange(end); else obj.convergenceAnalysis.convergencePoint(i) = convergenceIdx; obj.convergenceAnalysis.stableBER(i) = berValues(convergenceIdx); obj.convergenceAnalysis.convergenceSNR(i) = obj.snrRange(convergenceIdx); end end end function obj = analyzeModulationImpact(obj) % 调制方式影响分析 if isfield(obj.params, 'signalModulations') && ~isempty(obj.params.signalModulations) modTypes = unique(obj.params.signalModulations); else % 如果没有指定调制方式,默认为所有信号相同 modTypes = {'Unknown'}; obj.params.signalModulations = repmat(modTypes, 1, obj.params.numSignals); end numModTypes = length(modTypes); obj.modulationAnalysis = struct(... 'modulationTypes', {modTypes}, ... 'avgBER', zeros(1, numModTypes), ... 'avgSNR', zeros(1, numModTypes), ... 'sensitivity', zeros(1, numModTypes), ... 'minBER', zeros(1, numModTypes), ... 'maxThroughput', zeros(1, numModTypes)); for m = 1:numModTypes modType = modTypes{m}; signalIndices = find(strcmp(obj.params.signalModulations, modType)); if isempty(signalIndices) continue; end % 提取该调制方式的所有性能数据 berValues = obj.performanceCurves.ber(:, signalIndices); snrValues = obj.performanceCurves.snr(:, signalIndices); throughputValues = obj.performanceCurves.throughput(:, signalIndices); % 计算平均性能 obj.modulationAnalysis.avgBER(m) = mean(berValues(:)); obj.modulationAnalysis.avgSNR(m) = mean(snrValues(:)); % 计算灵敏度 (BER随SNR的变化率) meanBer = mean(berValues, 2); berDiff = diff(meanBer); snrDiff = diff(obj.snrRange'); obj.modulationAnalysis.sensitivity(m) = mean(berDiff ./ snrDiff); % 最佳性能 obj.modulationAnalysis.minBER(m) = min(berValues(:)); obj.modulationAnalysis.maxThroughput(m) = max(throughputValues(:)); end end function figHandle = plotPerformanceResults(obj, figHandle) % 创建性能分析图表 % 输入: figHandle - (可选)现有图形句柄 % 输出: figHandle - 图形句柄 if nargin < 2 || isempty(figHandle) || ~isvalid(figHandle) figHandle = figure('Name', 'TDM系统性能综合分析', ... 'Position', [100, 100, 1400, 900], ... 'Color', 'w'); else figure(figHandle); clf; end % 创建选项卡组 tabGroup = uitabgroup('Parent', figHandle); % 选项卡1: 核心性能指标 tab1 = uitab(tabGroup, 'Title', '核心指标'); ax1 = subplot(2, 3, 1, 'Parent', tab1); hold(ax1, 'on'); colors = lines(obj.params.numSignals); for i = 1:obj.params.numSignals plot(ax1, obj.snrRange, log10(obj.performanceCurves.ber(:, i)), ... 'Color', colors(i, :), 'LineWidth', 2, ... 'DisplayName', sprintf('信号 %d', i)); end hold(ax1, 'off'); title(ax1, '误码率(BER) vs 信噪比(SNR)'); xlabel(ax1, 'SNR (dB)'); ylabel(ax1, 'log_{10}(BER)'); grid(ax1, 'on'); legend(ax1, 'show'); % 2. 吞吐量 vs SNR曲线 ax2 = subplot(2, 3, 2, 'Parent', tab1); hold(ax2, 'on'); for i = 1:obj.params.numSignals plot(ax2, obj.snrRange, obj.performanceCurves.throughput(:, i), ... 'Color', colors(i, :), 'LineWidth', 2, ... 'DisplayName', sprintf('信号 %d', i)); end hold(ax2, 'off'); title(ax2, '吞吐量 vs 信噪比(SNR)'); xlabel(ax2, 'SNR (dB)'); ylabel(ax2, '吞吐量 (1 - BER)'); grid(ax2, 'on'); % 3. 调制方式性能对比 ax3 = subplot(2, 3, 3, 'Parent', tab1); modTypes = obj.modulationAnalysis.modulationTypes; numModTypes = length(modTypes); barValues = [obj.modulationAnalysis.avgBER; ... obj.modulationAnalysis.avgSNR]; hBar = bar(ax3, barValues'); set(ax3, 'XTickLabel', modTypes); title(ax3, '调制方式性能对比'); ylabel(ax3, '性能指标'); legend(ax3, {'平均BER', '平均SNR'}, 'Location', 'best'); grid(ax3, 'on'); % 添加数值标签 for i = 1:numModTypes text(ax3, i, barValues(1, i), sprintf('%.2e', barValues(1, i)), ... 'VerticalAlignment', 'bottom', 'HorizontalAlignment', 'center'); text(ax3, i, barValues(2, i), sprintf('%.1f dB', barValues(2, i)), ... 'VerticalAlignment', 'top', 'HorizontalAlignment', 'center'); end % 4. 收敛点分析 ax4 = subplot(2, 3, 4, 'Parent', tab1); convergencePoints = obj.convergenceAnalysis.convergencePoint; stableBER = obj.convergenceAnalysis.stableBER; yyaxis(ax4, 'left'); bar(ax4, convergencePoints, 'FaceColor', [0.2 0.6 0.8]); ylabel(ax4, '收敛点 (SNR索引)'); yyaxis(ax4, 'right'); plot(ax4, log10(stableBER), 'o-', 'LineWidth', 2, 'MarkerSize', 8); ylabel(ax4, 'log_{10}(稳定BER)'); title(ax4, '信号收敛分析'); xlabel(ax4, '信号编号'); grid(ax4, 'on'); legend(ax4, {'收敛点', '稳定BER'}); % 5. SNR敏感性分析 ax5 = subplot(2, 3, 5, 'Parent', tab1); sensitivity = obj.detailedMetrics.snrSensitivity; bar(ax5, sensitivity, 'FaceColor', [0.8 0.2 0.2]); title(ax5, 'SNR敏感性分析'); xlabel(ax5, '信号编号'); ylabel(ax5, 'BER变化率 / dB'); grid(ax5, 'on'); % 添加数值标签 for i = 1:length(sensitivity) text(ax5, i, sensitivity(i), sprintf('%.2e', sensitivity(i)), ... 'VerticalAlignment', 'bottom', 'HorizontalAlignment', 'center'); end % 6. 综合性能评分 ax6 = subplot(2, 3, 6, 'Parent', tab1); % 性能评分公式: 权重分配 performanceScore = 0.4 * (1 - obj.detailedMetrics.avgBER) + ... 0.3 * (obj.detailedMetrics.avgSNR / 30) + ... 0.2 * obj.detailedMetrics.maxThroughput + ... 0.1 * (1 - abs(obj.detailedMetrics.snrSensitivity)); bar(ax6, performanceScore, 'FaceColor', [0.5 0.2 0.8]); title(ax6, '信号综合性能评分'); xlabel(ax6, '信号编号'); ylabel(ax6, '性能评分 (0-1)'); ylim(ax6, [0 1]); grid(ax6, 'on'); % 添加数值标签 for i = 1:length(performanceScore) text(ax6, i, performanceScore(i), sprintf('%.3f', performanceScore(i)), ... 'VerticalAlignment', 'bottom', 'HorizontalAlignment', 'center'); end % 添加整体标题 annotation(figHandle, 'textbox', [0.3 0.95 0.4 0.05], 'String', ... sprintf('TDM系统综合分析 (策略: %s, 总时隙: %d)', ... obj.params.strategy, obj.params.totalSlots), ... 'EdgeColor', 'none', 'HorizontalAlignment', 'center', ... 'FontSize', 14, 'FontWeight', 'bold'); % 选项卡2: 详细数据视图 tab2 = uitab(tabGroup, 'Title', '详细数据'); axTable = uitable('Parent', tab2, ... 'Data', obj.getPerformanceTableData(), ... 'ColumnName', {'信号', '调制方式', '平均BER', '平均SNR(dB)', '最低BER', '最大吞吐量', 'SNR敏感性', '10dB BER', '20dB BER'}, ... 'Units', 'normalized', ... 'Position', [0.05, 0.05, 0.9, 0.9], ... 'FontSize', 10); % 选项卡3: 收敛性分析 tab3 = uitab(tabGroup, 'Title', '收敛性'); ax7 = subplot(1, 2, 1, 'Parent', tab3); hold(ax7, 'on'); for i = 1:obj.params.numSignals berData = obj.performanceCurves.ber(:, i); convergenceSNR = obj.convergenceAnalysis.convergenceSNR(i); convergenceIdx = obj.convergenceAnalysis.convergencePoint(i); plot(ax7, obj.snrRange, log10(berData), ... 'Color', colors(i, :), 'LineWidth', 2, ... 'DisplayName', sprintf('信号 %d', i)); % 标记收敛点 plot(ax7, convergenceSNR, log10(berData(convergenceIdx)), ... 'o', 'MarkerSize', 10, 'MarkerFaceColor', colors(i, :)); end hold(ax7, 'off'); title(ax7, '收敛点可视化'); xlabel(ax7, 'SNR (dB)'); ylabel(ax7, 'log_{10}(BER)'); grid(ax7, 'on'); legend(ax7, 'show'); ax8 = subplot(1, 2, 2, 'Parent', tab3); convergenceSNR = obj.convergenceAnalysis.convergenceSNR; bar(ax8, convergenceSNR, 'FaceColor', [0.3 0.7 0.5]); title(ax8, '收敛点SNR值'); xlabel(ax8, '信号编号'); ylabel(ax8, '收敛SNR (dB)'); grid(ax8, 'on'); end function tableData = getPerformanceTableData(obj) % 生成性能数据表格 numSignals = obj.params.numSignals; tableData = cell(numSignals, 9); for i = 1:numSignals tableData{i, 1} = i; % 信号编号 % 调制方式 if isfield(obj.params, 'signalModulations') && length(obj.params.signalModulations) >= i tableData{i, 2} = obj.params.signalModulations{i}; else tableData{i, 2} = 'N/A'; end % 性能数据 tableData{i, 3} = sprintf('%.2e', obj.detailedMetrics.avgBER(i)); tableData{i, 4} = sprintf('%.2f', obj.detailedMetrics.avgSNR(i)); tableData{i, 5} = sprintf('%.2e', obj.detailedMetrics.minBER(i)); tableData{i, 6} = sprintf('%.4f', obj.detailedMetrics.maxThroughput(i)); tableData{i, 7} = sprintf('%.2e', obj.detailedMetrics.snrSensitivity(i)); tableData{i, 8} = sprintf('%.2e', obj.detailedMetrics.berAt10dB(i)); tableData{i, 9} = sprintf('%.2e', obj.detailedMetrics.berAt20dB(i)); end end function exportToExcel(obj, filename) % 导出性能数据到Excel % 输入: filename - 输出文件名 if nargin < 2 filename = 'TDM_Performance_Analysis.xlsx'; end % 创建数据表 sheet1 = obj.getPerformanceTableData(); headers = {'信号', '调制方式', '平均BER', '平均SNR(dB)', '最低BER', '最大吞吐量', 'SNR敏感性', '10dB BER', '20dB BER'}; % 写入详细性能数据 xlswrite(filename, [headers; sheet1], '详细性能'); % 写入SNR扫描数据 snrHeaders = {'SNR(dB)'}; for i = 1:obj.params.numSignals snrHeaders{end+1} = sprintf('信号%d_BER', i); snrHeaders{end+1} = sprintf('信号%d_吞吐量', i); end snrData = num2cell([obj.snrRange', ... obj.performanceCurves.ber, ... obj.performanceCurves.throughput]); xlswrite(filename, [snrHeaders; snrData], 'SNR扫描'); % 写入调制方式分析 modHeaders = {'调制方式', '平均BER', '平均SNR(dB)', '灵敏度', '最低BER', '最大吞吐量'}; modData = cell(length(obj.modulationAnalysis.modulationTypes), 6); for m = 1:length(obj.modulationAnalysis.modulationTypes) modData{m, 1} = obj.modulationAnalysis.modulationTypes{m}; modData{m, 2} = obj.modulationAnalysis.avgBER(m); modData{m, 3} = obj.modulationAnalysis.avgSNR(m); modData{m, 4} = obj.modulationAnalysis.sensitivity(m); modData{m, 5} = obj.modulationAnalysis.minBER(m); modData{m, 6} = obj.modulationAnalysis.maxThroughput(m); end xlswrite(filename, [modHeaders; modData], '调制分析'); disp(['性能数据已导出到: ' filename]); end end methods (Static) function analyzer = analyzeSystem(params, customSNR) % 静态方法: 完整分析工作流 % 输入: params - 系统参数 % customSNR - (可选)自定义SNR范围 analyzer = TDMPerformanceAnalyzer(params); if nargin > 1 analyzer = analyzer.runPerformanceAnalysis(customSNR); else analyzer = analyzer.runPerformanceAnalysis(); end % 显示结果 fig = analyzer.plotPerformanceResults(); % 导出结果 exportFilename = sprintf('TDM_Analysis_%s_%dSlots.xlsx', ... params.strategy, params.totalSlots); analyzer.exportToExcel(exportFilename); end end end
最新发布
06-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值