kron matlab_kron的实战例子: 寻找最大的回文乘积

MATLAB中kron构造乘积向量的应用
本文介绍了MATLAB中kron的用法,通过寻找一定范围内两数乘积为最大回文数的题目展开。亮点一是用kron构造“乘积向量”,比传统矩阵乘法少一步;二是for循环直接用向量;还提及用isequal比较字符串、int2str转换数字等内容。

08db290229968fa4583268892d0074ad.png

关于kron, 我写过另一篇文章, 读者可以看一下, 熟悉一下kron的用法:

菡姐:使用kron来实现repmat, repelem的功能​zhuanlan.zhihu.com
a0f7a21b10f8e80db477810d2f3a3fbf.png

题目的链接:

Project Euler: Problem 4, Palindromic numbers​ww2.mathworks.cn

题目描述:

A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 99.
Find the largest palindrome made from the product of numbers less than or equal to the input number.
Thank you to Project Euler Problem 4

意思很简单, 寻找一定范围内的两个数的乘积, 必须是回文数, 并且是最大的.

用数学语言表达大概就是:

max c = a*b
std:
1 <= a <= x
1 <= b <= x
c is palindromic number

回文数的定义是: 左右颠倒过来, 很原先一模一样, 即左右对称, 就像这篇文章的封面图一样.

先看我写的代码, 没有对比就没有伤害 o(╥﹏╥)o :

function ans = euler004(x)
v = x-99:x; % 这是v = 1:x的变形, 提高了搜索的下限, 目的为了节省内存和运算量.
M = unique(v'*v); % 利用矩阵乘法, 生成了乘积矩阵, 然后用unique去重, 以及压缩成向量
strM = string(M); % 变成string型, 目的是方便进行左右颠倒
M(find(reverse(strM) == strM, 1, 'last')); % 检验左右对称性
end

代码有注释, 就不多做解释了.

然后是最佳代码(size最小, 并且不是作弊代码, 比如使用regexp或者直接插入答案的)

function y = euler004(x)
for y = sort(kron(1:x,1:x),'descend')
    if isequal(int2str(y),flip(int2str(y)))
        return
    end
end

分析:

1 使用了kron来构造"乘积向量".

这个是最大的亮点:

因为一般思路是利用矩阵乘法或者bsxfun来构造"乘积矩阵".

乘积向量相比乘积矩阵的优势是: 乘积矩阵在排序之前必须变形成向量, 多了一个步骤, 而kron直接就生成了向量, 相比之下, 少了一个步骤.

2 第二个亮点是for循环里面, 直接使用了该"乘积向量", 而不是在for循环里面生成索引.

for循环里面直接使用向量的做法, 相对来说是比较冷门技巧, 很多使用MATLAB多年的人都不知道.

举个例子说明:

例子1, 当V为行向量时, for循环每次取其中一个元素(标量).

V = [2, 5, 1.3];
cnt = 0;
for v = V
    cnt = cnt + 1;
    v
end
cnt

运行结果:

v =
     2
v =
     5
v =
                       1.3
cnt =
     3

可以看到, 每次取一个元素, 并且循环了3次.

例子2, 当V为列向量时:

V = [2;5;1.3];
cnt = 0;
for v = V
    cnt = cnt + 1;
    v
end
cnt

运行结果:

v =
                         2
                         5
                       1.3
cnt =
     1

运行结果与很多人预期的不同, 直接取了整个列向量, 因此, 也只需要循环一次.

例子3, 当V为矩阵时:

V = [1, 2;3, 4];
cnt = 0;
for v = V
    cnt = cnt + 1;
    v
end
cnt

运行结果:

v =
     1
     3
v =
     2
     4
cnt =
     2

每次取其中一列, 有多少列就循环多少次.

从这三个例子中不难总结出规律:

MATLAB的for循环是以列为单位的.

3 使用了isequal来比较字符串.

也可以使用strcmp来比较字符串.

相比strcmp, isequal的使用范围更广.

4 使用了int2str, 也可以使用num2str

两者在整数情况下, 效果一样, 在有小数的情况下, int2str会先取整.

>> num2str(134)
ans =
    '134'
>> int2str(134)
ans =
    '134'
>> int2str(134.4)
ans =
    '134'
>> num2str(134.4)
ans =
    '134.4'
>> int2str(-134.4)
num2str(-134.4)
ans =
    '-134'
ans =
    '-134.4'
>> int2str(134.9)
num2str(134.9)
ans =
    '135'
ans =
    '134.9'
>> int2str(-134.9)
num2str(-134.9)
ans =
    '-135'
ans =
    '-134.9'

取整的方法明显为round.

这是MATLAB文档里面的解释:

chr = int2str(N) treats N as a matrix of integers and converts it to a character array that represents the integers. If N contains floating-point values, int2str rounds them before conversion.

创作不易, 请大家"素质三连": 点赞, 收藏, 分享.

``` clc; clear; close all; % 系统参数设置 fs = 1000; % 采样频率,单位 Hz T = 0.25; % 信号持续时间,单位 s t = 0:1/fs:T - 1/fs; % 时间向量 N = length(t); % 信号长度 num_users = 4; % 用户数量 chip_rate = 10; % 码片速率 num_chips = chip_rate * N; % 码片总数 % 1. 生成相同的 0.25s 随机信号(非二进制) info_signal = randn(1, N); % 2. 生成 Walsh 扩频码 walsh_codes = hadamard(num_users); % 3. 扩频操作 spread_signals = zeros(num_users, num_chips); for u = 1:num_users % 重复信息信号以匹配码片数量 repeated_info = repmat(info_signal, 1, chip_rate); % 重复 Walsh 码以匹配码片数量 repeated_walsh = repmat(walsh_codes(u, :), 1, num_chips/num_users); % 与 Walsh 码相乘进行扩频 spread_signals(u, :) = repeated_info .* repeated_walsh; end % 4. 调制到子载波上 % 假设采用 BPSK 调制,这里简单认为信号值就是调制后的值 modulated_signals = spread_signals; % 5. IFFT 处理生成 OFDM 信号 ofdm_signal = sum(ifft(modulated_signals), 1); % 6. 接收端处理 % 假设无信道干扰,接收信号就是 OFDM 信号 received_signal = ofdm_signal; % 7. FFT 解调出子载波 demodulated_subcarriers = fft(received_signal); % 8. 解扩操作 despread_signals = zeros(num_users, N); for u = 1:num_users % 重复 Walsh 码以匹配子载波数量 repeated_walsh = repmat(walsh_codes(u, :), 1, num_chips/num_users); % 解扩 despread = demodulated_subcarriers .* repeated_walsh; % 按信息比特分组求并除以码片数 despread_grouped = reshape(despread, chip_rate, N); despread_signals(u, :) = sum(despread_grouped, 1) / chip_rate; end % 初始用户信号时域图 figure; plot(t, info_signal); title('初始用户信号(时域)'); xlabel('时间 (s)'); ylabel('幅度'); % 初始用户信号频域图 figure; f = (-N/2:N/2 - 1)*(fs/N); X = fftshift(fft(info_signal)); plot(f, abs(X)); title('初始用户信号(频域)'); xlabel('频率 (Hz)'); ylabel('幅度'); % 四个用户扩频后信号时域图 figure; t_chip = 0:1/(fs*chip_rate):T - 1/(fs*chip_rate); for u = 1:num_users subplot(num_users, 1, u); plot(t_chip, spread_signals(u, :)); title(['用户 ', num2str(u), ' 扩频后信号(时域)']); xlabel('时间 (s)'); ylabel('幅度'); end % 四个用户扩频后信号频域图 figure; for u = 1:num_users subplot(num_users, 1, u); N_chip = length(spread_signals(u, :)); f_chip = (-N_chip/2:N_chip/2 - 1)*(fs*chip_rate/N_chip); X_chip = fftshift(fft(spread_signals(u, :))); plot(f_chip, abs(X_chip)); title(['用户 ', num2str(u), ' 扩频后信号(频域)']); xlabel('频率 (Hz)'); ylabel('幅度'); end % 四个用户调制后信号时域图 figure; for u = 1:num_users subplot(num_users, 1, u); plot(t_chip, modulated_signals(u, :)); title(['用户 ', num2str(u), ' 调制后信号(时域)']); xlabel('时间 (s)'); ylabel('幅度'); end % 四个用户调制后信号频域图 figure; for u = 1:num_users subplot(num_users, 1, u); N_mod = length(modulated_signals(u, :)); f_mod = (-N_mod/2:N_mod/2 - 1)*(fs*chip_rate/N_mod); X_mod = fftshift(fft(modulated_signals(u, :))); plot(f_mod, abs(X_mod)); title(['用户 ', num2str(u), ' 调制后信号(频域)']); xlabel('频率 (Hz)'); ylabel('幅度'); end % OFDM 信号时域图 figure; plot(t_chip, ofdm_signal); title('OFDM 信号(时域)'); xlabel('时间 (s)'); ylabel('幅度'); % OFDM 信号频域图 figure; N_ofdm = length(ofdm_signal); f_ofdm = (-N_ofdm/2:N_ofdm/2 - 1)*(fs*chip_rate/N_ofdm); X_ofdm = fftshift(fft(ofdm_signal)); plot(f_ofdm, abs(X_ofdm)); title('OFDM 信号(频域)'); xlabel('频率 (Hz)'); ylabel('幅度'); % 四个用户解扩后信号时域图 figure; for u = 1:num_users subplot(num_users, 1, u); plot(t, despread_signals(u, :)); title(['用户 ', num2str(u), ' 解扩后信号(时域)']); xlabel('时间 (s)'); ylabel('幅度'); end % 四个用户解扩后信号频域图 figure; for u = 1:num_users subplot(num_users, 1, u); N_despread = length(despread_signals(u, :)); f_despread = (-N_despread/2:N_despread/2 - 1)*(fs/N_despread); X_despread = fftshift(fft(despread_signals(u, :))); plot(f_despread, abs(X_despread)); title(['用户 ', num2str(u), ' 解扩后信号(频域)']); xlabel('频率 (Hz)'); ylabel('幅度'); end```完善代码
最新发布
03-12
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值