计算统计特征(正态分布)函数及实例

清泛原创
main函数:
#include "stdafx.h"
#include "stdev.h"
#include <map>

int _tmain(int argc, _TCHAR* argv[])
{
	std::map<int, int> map_test;
	map_test[0] = 100;
	map_test[5] = 80;
	map_test[2] = 10;
	map_test[8] = 99;
	map_test[4] = 102;

	StdevInfo stdev_info;
	stdev_info.init();

	stdev_info.caculate_stdev_info(map_test.begin(), map_test.end(),
		[](const std::pair<int, int> &pr) { return pr.second; });

	//if (value > stdev_info._ave * 2) { ... }

	return 0;
}

stdev.h
#ifndef _UTILITY_STDEV_H_
#define _UTILITY_STDEV_H_
/*
 * 计算统计特征的函数
 */
#define _USE_MATH_DEFINES
#include <algorithm>
#include <math.h>
#include <float.h>
#include <crtdbg.h>
#include <vector>

	struct StdevInfo
	{
		static const double MAX_VAR;
		double _ave;
		//double _var;
		double _sam_stdev;
		double _all_stdev;
		double _sum;
		double _sum_2;
		int _count;
		double _min_v;
		double _max_v;

		StdevInfo()
			: _ave(0.0)
			//, _var(MAX_VAR)
			, _sam_stdev(sqrt(MAX_VAR))
			, _all_stdev(0.0)
			, _sum(0.0)
			, _sum_2(0.0)
			, _count(0)
			, _min_v(0.0)
			, _max_v(0.0)
		{}

		void init(void)
		{
			_ave = 0.0;
			//_var = 0.0;
			//_stdev = 0.0;
			_sum = 0.0;
			_sum_2 = 0.0;
			_count = 0;
			_min_v = 0.0;
			_max_v = 0.0;

			//_var   = MAX_VAR;
			_all_stdev = 0.0;
			_sam_stdev = sqrt(MAX_VAR);
		}

		template<typename I, typename F, typename FILTER>
		inline void caculate_stdev_info(I b, I e, const F &f, const FILTER &filter);

		template<typename I, typename F>
		inline void caculate_stdev_info(I b, I e, const F &f);

		inline void add_value(double v);
		inline void del_value(double v);
		inline void change_value(double v1, double v2)
		{
			del_value(v1);
			add_value(v2);
		}

		inline double sam_var(void) const { return _sam_stdev * _sam_stdev; }
		inline double all_var(void) const { return _all_stdev * _all_stdev; }
	};

	class StdevCaculator {
	public:
		static void add_value(StdevInfo &info, double v);
		static void del_value(StdevInfo &info, double v);

		template<typename I, typename F, typename FILTER>
		static void caculate_stdev_info(StdevInfo &info, I b, I e, const F &f, const FILTER &filter)
		{
			info.init();

			int count = 0;
			double sum_v = 0.0, sum_2_v = 0.0;
			double max_v = -10000000000.0;
			double min_v = 10000000000.0;
			double v;
			for (auto i = b; i != e; ++i) {
				if (!filter(*i))
					continue;

				++count;
				v = f(*i);
				if (v > max_v)
					max_v = v;
				if (v < min_v)
					min_v = v;


				sum_v   += v;
				sum_2_v += v * v;
			}

			if (count < 1)
				return;

			double ave_v = sum_v / count;
			info._sum    = sum_v;
			info._sum_2  = sum_2_v;
			info._count  = count;
			info._ave    = ave_v;
			info._max_v  = max_v;
			info._min_v  = min_v;

			if (count < 2) {
				//info._var   = StdevInfo::MAX_VAR;
				//info._all_stdev = 0.0;
				//info._sam_stdev = sqrt(StdevInfo::MAX_VAR);
				return;
			}

			double sum_diff2 = 0.0;
			for (auto i = b; i != e; ++i) {
				if (!filter(*i))
					continue;

				v = f(*i);
				double diff_v = v - ave_v;
				sum_diff2 += diff_v * diff_v;
			}
			info._sam_stdev = sqrt(sum_diff2 / (count - 1)); // 样本标准差要减1
			info._all_stdev = sqrt(sum_diff2 / count);
		}

		template<typename I, typename F>
		static void caculate_stdev_info(StdevInfo &info, I b, I e, const F &f)
		{
			info.init();

			int count = 0;
			double sum_v = 0.0, sum_2_v = 0.0;
			double max_v = -10000000000.0;
			double min_v = 10000000000.0;
			double v;
			for (auto i = b; i != e; ++i) {
				++count;
				v = f(*i);
				if (v > max_v)
					max_v = v;
				if (v < min_v)
					min_v = v;


				sum_v   += v;
				sum_2_v += v * v;
			}

			if (count < 1)
				return;

			double ave_v = sum_v / count;
			info._sum    = sum_v;
			info._sum_2  = sum_2_v;
			info._count  = count;
			info._ave    = ave_v;
			info._max_v  = max_v;
			info._min_v  = min_v;

			if (count < 2) {
				//info._var   = StdevInfo::MAX_VAR;
				//info._all_stdev = 0.0;
				//info._sam_stdev = sqrt(StdevInfo::MAX_VAR);
				return;
			}

			double sum_diff2 = 0.0;
			for (auto i = b; i != e; ++i) {
				v = f(*i);
				double diff_v = v - ave_v;
				sum_diff2 += diff_v * diff_v;
			}
			info._sam_stdev = sqrt(sum_diff2 / (count - 1)); // 样本标准差要减1
			info._all_stdev = sqrt(sum_diff2 / count);
		}
	};

	template<typename I, typename F, typename FILTER>
	inline void StdevInfo::caculate_stdev_info(I b, I e, const F &f, const FILTER &filter)
	{
		StdevCaculator::caculate_stdev_info(*this, b, e, f, filter);
	}

	template<typename I, typename F>
	inline void StdevInfo::caculate_stdev_info(I b, I e, const F &f)
	{
		StdevCaculator::caculate_stdev_info(*this, b, e, f);
	}

	inline void StdevInfo::add_value(double v)
	{
		StdevCaculator::add_value(*this, v);
	}

	inline void StdevInfo::del_value(double v)
	{
		StdevCaculator::del_value(*this, v);
	}

#endif // !_UTILITY_STDEV_H_

stdev.cpp
#include "stdev.h"

	const double StdevInfo::MAX_VAR = DBL_MAX / 100.0;

	void StdevCaculator::add_value(StdevInfo &info, double v)
	{
		double sum   = info._sum;
		double sum_2 = info._sum_2;

		info._sum   += v;
		info._sum_2 += v * v;
		++info._count;
		if (info._count > 1) {
			if (v > info._max_v)
				info._max_v = v;
			if (v < info._min_v)
				info._min_v = v;
		} else {
			info._max_v = info._min_v = v;
		}

		info._ave = info._sum / info._count;

		if (info._count < 2) {
			//info._var   = StdevInfo::MAX_VAR;
			info._all_stdev = 0.0;
			info._sam_stdev = sqrt(StdevInfo::MAX_VAR);
			return;
		}

		double var_sum = sum_2 + v * v + info._count * info._ave * info._ave - 2 * info._ave * (sum + v);
		//_ASSERTE(var_sum >= -DBL_EPSILON * 100);
		if (var_sum < 0.0)
			var_sum = 0.0;
		//info._var = var_sum / (info._count - 1);
		info._sam_stdev = sqrt(var_sum / (info._count - 1));
		info._all_stdev = sqrt(var_sum / (info._count));

		_ASSERTE(_finite(info._sam_stdev));
		_ASSERTE(_finite(info._all_stdev));
		_ASSERTE(_finite(info._ave));
	}


	void StdevCaculator::del_value(StdevInfo &info, double v)
	{
		double sum   = info._sum;
		double sum_2 = info._sum_2;

		info._sum   -= v;
		info._sum_2 -= v * v;
		--info._count;


		if (info._count > 1) {
			/* NOTE: 删除时, 最大最小值无法还原 */
			/*
			if (v > info._max_v)
				info._max_v = v;
			if (v < info._min_v)
				info._min_v = v;
			 */
		} else {
			info._max_v = info._min_v = v;
		}

		if (info._count > 0)
			info._ave = info._sum / info._count;
		else
			info._ave = 0.0;

		if (info._count < 2) {
			info._all_stdev = 0.0;
			info._sam_stdev = sqrt(StdevInfo::MAX_VAR);
			return;
		}

		double var_sum = sum_2 - v * v + info._count * info._ave * info._ave - 2 * info._ave * (sum - v);
		info._sam_stdev = sqrt(var_sum / (info._count - 1));
		info._all_stdev = sqrt(var_sum / (info._count));
	}

统计 正态分布

分享到:
评论加载中,请稍后...
创APP如搭积木 - 创意无限,梦想即时!
回到顶部