如何将-360~360范围值映射为45倍数序列?求映射算法
角度值映射为45倍数序列的算法问题
我有范围在-360至360之间的数值,需要将其映射为对应45倍数的序列(重点关注映射算法本身)。
以下是输入(IN)、中间步骤(STEP)及期望输出(OUT)的对应关系:
| IN | -360 | -315 | -270 | -225 | -180 | -135 | -90 | -45 | 0 | 45 | 90 | 135 | 180 | 225 | 270 | 325 | 360 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| STEP | 0 | 1 | 0 | -1 | 0 | 1 | 0 | -1 | 0 | 1 | 0 | -1 | 0 | 1 | 0 | -1 | 0 |
| OUT | 0 | 45 | 0 | -45 | 0 | 45 | 0 | -45 | 0 | 45 | 0 | -45 | 0 | 45 | 0 | -45 | 0 |
问题
请问是否可以/应该使用线性变换来实现?或者如何编写类似如下的映射函数来完成该需求?
var mapRange = function(base_range, target_range, s) { return target_range[0] + (s - base_range[0]) * (target_range[1] - target_range[0]) / (base_range[1] - base_range[0]); };
补充说明:原以为将数值转换到-1至1范围后直接乘以45即可实现,现已添加期望输出。
解答
1. 能否用线性变换实现?
不能。线性变换的核心是输入与输出保持连续的比例关系且单调变化,但你的映射规则是周期性的离散跳跃(比如输入从-360到-315增加45,输出从0到45;但输入从-315到-270同样增加45,输出却从45回到0),完全不符合线性变换的特性。你提供的mapRange函数是典型的线性区间映射,仅适用于连续的线性转换场景,无法处理这种周期性离散映射需求。
2. 实现思路与代码
观察映射规律可以发现:
- 所有90度倍数的输入(如-360、-270、0、90等),输出均为0;
- 输入为45度奇数倍时,根据所在的90度周期区间,输出为45或-45:
- 处于
[90k, 90k+45]区间(k为整数)时,输出45; - 处于
[90k+45, 90k+90]区间时,输出-45;
- 处于
基于此可以编写如下JavaScript实现函数,同时支持离散的45倍数输入和连续的任意角度输入:
function mapAngleTo45Multiple(angle) { // 将角度归一化到0-360的范围,兼容负数和超出-360~360的输入 const normalizedAngle = ((angle % 360) + 360) % 360; const mod90 = normalizedAngle % 90; // 处理90度倍数的输入,直接返回0 if (mod90 === 0) { return 0; } const cycle = Math.floor(normalizedAngle / 90); // 处理45度倍数的输入,或连续输入的区间映射 switch (cycle) { case 0: // 0°-90°区间 return normalizedAngle <= 45 ? 45 : 0; case 1: // 90°-180°区间 return normalizedAngle <= 135 ? 0 : -45; case 2: // 180°-270°区间 return normalizedAngle <= 225 ? 45 : 0; case 3: // 270°-360°区间 return normalizedAngle <= 315 ? 0 : -45; default: return 0; } }
函数验证
代入表格中的输入值测试:
mapAngleTo45Multiple(-360)→ 0mapAngleTo45Multiple(-315)→ 45mapAngleTo45Multiple(-225)→ -45mapAngleTo45Multiple(45)→ 45mapAngleTo45Multiple(135)→ -45mapAngleTo45Multiple(360)→ 0
所有结果均符合期望输出。
内容的提问来源于stack exchange,提问作者D.icon
相关产品推荐
相关产品推荐

