循环的角度求均值

为什么会讨论到这么简单的问题?

举几个例子,角度范围为0~360度,0度和360度是重合的,不妨先算法下面角度的均值,

[10, 30] = 20 结果正确

[20, 100] = 60 结果正确

[160, 200]= 180 结果正确

[0, 360] = 180 因为360度和0度重合,这个结果貌似不是我们想要的,结果360度才合理

[20, 300] = 160 要能求得均值为340度就好了

不知看出什么问题没有——角度求均值不再是简单的算术均值!

修正的0~360度求均值方案

从上面的结果也可以知道,有些情况下角度均值就是算术平均值,那什么情况下不是求算术平均值呢?

如上图,当α<β时,当β-α > 180时,(α+β)/2不再是要求的结果;同理,α<β时,α-β > 180时不再是求算术平均值。

综合这两种情况,当|α-β|>180情况下不是求算术平均值。这种情况下期望的角度均值为(以α小于β为例):

同理,因为上面的表达式中的α与β对称,所以α大于β计算的结果也一样。因此可知,非算术平均值的情况只要在算术平均值的基础上加180就可以了,因此归纳如下:

180,%20%5Ctheta=%5Cfrac%7B%5Calpha+%5Cbeta%7D%7B2%7D+180%20%5Catop%20%7C%5Calpha-%5Cbeta%7C

上面仅是两个角度值的平均,通过两个角度的差值做判别条件确定是否是算术均值,然而,多个的呢?

多个的角度均值显得有些复杂,这需要用户对输入输出角度范围提供约束,这里不妨将命题变成:考虑到相邻角度在时间上的相关性,设相邻的两个输入角度值偏移值不会大于180度,在这种情况下,只要考虑0~360度的突变情况就可以了。

直接看matlab程序吧(参考资料2),

function [avg] = avg_degree(angles)
% 计算角度平均值,注意0-360度情况

last = angles(1);
sum = angles(1);
for i=2:length(angles)
    diff = mod(angles(i)-angles(i-1)+180,360)-180;
    last = last + diff;
    sum = sum + last;
end
avg = mod(sum/length(angles), 360);

end

给个自己使用的C程序也有,只不过求模用条件运算替换了,

#define ANGLE_DIFF(diff, x2, x1) \
do {  \
    diff = x2-x1+180; \
    if (diff < 0) {  \
        diff = diff + 360 - 180;  \
    } else if (diff > 360) {  \
        diff = diff - 360 - 180;  \
    } else {  \
        diff = diff - 180;  \
    }  \
} while(0)

float angle_avg(float *angle, uint32_t n)
{
    float diff = 0;
    float last = angle[0];
    float sum  = angle[0];
    uint32_t i = 0;

    for (i=1; i<n; i++) {
        /* diff = mod(angle[i]-angle[i-1]+180,360)-180 */
        ANGLE_DIFF(diff, angle[i], angle[i-1]);
        last += diff;
        sum  += last;
    } 

    return sum/n;
}

其中的DIFF宏定义用于计算两个角度差值。

文献综述

维基百科角度出现循环的变量为圆周量,如上面的角度值、一天的24小时等。

Wikipedia中计算平均角度的方法:

参考文献1中给出了关于圆周变量更细致的数学分析与描述,是一份难得的资料,参考文献2是StackOverflow上关于圆周角度的探讨,作为对该问题的理解很有帮助。

参考

  1. CodeProject: Circular Values Math and Statistics with C++11
  2. Stackoverflow: How do you calculate the average of a set of angles?
  3. Wikipedia

循环的角度求均值,布布扣,bubuko.com

时间: 2024-08-26 12:58:43

循环的角度求均值的相关文章

在平面内,已知一个矩形的四个角坐标,将矩形绕中心点转动一个角度,求旋转后的角坐标.

在平面内,已知一个矩形的四个角坐标,将矩形绕中心点转动一个角度,求旋转后的角坐标.也就是已知半径,求每个点旋转后的坐标. 把旋转前和旋转后的点加上中心点看成一个等腰三角形就好解决了,不用扇形公式,而是用三角形公式.假设矩形的左上角为(left, top),右下角为(right, bottom),则矩形上任意点(x0, y0)绕其中心(xcenter,ycenter)逆时针旋转angle角度后,新的坐标位置(x′, y′)的计算公式为: xcenter = (right - left + 1) /

循环-08. 二分法求多项式单根(20)

1 #include<iostream> 2 #include<cmath> 3 #include<iomanip> 4 using namespace std; 5 double a3,a2,a1,a0; 6 double f(double x){ 7 return a3*pow(x,3)+a2*pow(x,2)+a1*x+a0; 8 } 9 int main(){ 10 double a,b,t=0.001; 11 cin>>a3>>a2&g

循环一维数组求最大子数组

题目: 随机出一个一维数组,设该数组为循环数组,求其最大小子数组. 一.设计思路 求最大子数组,就求出最大的连续正子数组. 将数组分为全负和有非负值两种情况.全负求出最大值即可. 在有非负值的情况下,先判断该随机数组的首尾是否相连,即首尾是否都大于等于零.如果首尾相连,则将该一维数组分为首.中.尾三部分,先求出首尾和S1,再求中间最大连续正子数组和S,令S1和S与maxS相比较,求出最大子数组:如果首尾不相连,则直接借鉴前一种情况中部的算法,求最大正子数组S. 二.源代码 1 //刘双渤,刘洪阳

一维循环的数组求出最大子数组的和

题目是:一维循环的数组求出最大子数组的和 老师刚给出这个题目时 ,求出一维子数组的最大子数组的和,当时我就想原来已经做过一个求出一维数组的最大子数组的和,能不能在此基础上延伸一下,于是我就想怎样利用原来的算法,后来我就想既然是还是求出最大子数组的和肯定原来的东西可以利用. 我想既然是循环,无外乎就是这个数组进行两遍,所以我感觉这样就可以再在这个数组后面申请一个和它长度相同,数的大小和顺序和它一样的数组,这样就起到了循环的目的,于是我就这样进行了,然后再调用原来的方法,这样就可以求出最大子数组的值

java代码:用for循环求和,求偶数和,求奇数和,打印水仙花数,统计水仙花数

用for循环求和,求偶数和,求奇数和,打印水仙花数,统计水仙花数package loop; public class For1 {public static void main(String[] args) {int sum=0;for(int x=0;x<=100;x++) {sum=sum+x;}System.out.println("100以内(含100)整数和:"+sum);System.out.println("------------------------

RNN 循环神经网络-BF 求导过程

RNN 循环神经网络-BF 求导过程 所有的RNN都具有一种重复神经网络模块的链式形式.在标准RNN中,这个重复的结构模块只有一个非常简单的结构,例如一个tanh层 在时间视角上的显示为下图: 求导BP 更新参数值 整体误差E等于每个时刻E_t的误差之和 整体损失对U/V/W进行求偏导 \[ ΔU=\frac{\partial E}{\partial U}=\sum_t \frac{\partial e_t}{\partial U} \] \[ ΔV=\frac{\partial E}{\par

Python求均值,方差,标准差

import numpy as nparr = [1,2,3,4,5,6]#求均值arr_mean = np.mean(arr)#求方差arr_var = np.var(arr)#求标准差arr_std = np.std(arr,ddof=1)print("平均值为:%f" % arr_mean)print("方差为:%f" % arr_var)print("标准差为:%f" % arr_std) 原文地址:https://www.cnblogs

结对开发--循环一维数组求最大子数组的和

结对人员:韩雪东,高扬 一.设计思路 这次编程我们主要是以以前的程序为基础,在此基础上通过改变数组元素的位置,形成新的数组,并通过调用我们之前找最大值的函数,找出每个数组的最大值,然后经过比较求得结果. 二.源代码 // shuzuhuan0327.cpp : Defines the entry point for the console application. //作者:韩雪东,高扬 //时间:2015/3/27 #include "stdafx.h" #include "

python学习——读取染色体长度(三、用循环或者函数求总长并获取最长染色体长度)

# 读取fasta # 解析每条序列的长度 chr_len = [10,20,30,40,50] # 求和 # 方法一:通过循环 total_len = 0 #定义total_len的初始长度 for len in chr_len: # 从列表chr_len中每次取一个值交给len total_len += len # 或者total_len = total_len + len # 方法二:通过函数sum() total_len = sum(chr_len) # 求最长染色体编号 max_len