之前遇到的一个客户需求就是计算标准化降水指数(SPI)。

主要参考的论文为:洪兴骏,等 “标准化降水指数SPI分布函数的适用性研究”。原文可以很容易搜索到。

论文将计算方法其实写的比较清楚了,本文主要提供其C++实现。

头文件

//SPI_Calculator.h

#include

#include

#include

#include

#include

using namespace std;

#ifndef SPICALCULATOR_H

#define SPICALCULATOR_H

class SPI_Calculator{

public:

/**

path is the file that provides the data of rain fall

file format:

yearamount of precipitation

yearamount of precipitation

.

.

.

*/

SPI_Calculator(char* path);

/**

parameter is the year to get the SPI

return SPI

*/

double getSPI(int year);

double f_probabilityDensity(double x);

double f_gamma(double z, unsigned Ntermsx);

double integral(double a,double b);

void printYears();

void printSPI();

void test();

private:

bool readData(char* path);

void calculateParameter();

vector> dataTable;

double dataCounter,zeroCounter;

double xAver; //average number of samples

double c0,c1,c2,d1,d2,d3; //const parameter

double para_A, para_Gamma, para_Beta;

};

#endif

实现文件:

#include"SPI_Calculator.h"

SPI_Calculator::SPI_Calculator(char* path){

c0 = 2.515517;

c1 = 0.802853;

c2 = 0.010328;

d1 = 1.432788;

d2 = 0.189269;

d3 = 0.001308;

dataCounter = 0;

zeroCounter = 0;

if(!readData(path)){

cout<

system("pause");

exit(0);

}

calculateParameter();

}

bool SPI_Calculator::readData(char* path){

fstream dataIn(path,ios::in);

if(!dataIn.is_open()){

cout<

return false;

}

pair tempPair;

while(!dataIn.eof()){

dataIn>>tempPair.first;

dataIn>>tempPair.second;

dataTable.push_back(tempPair);

dataCounter ++;

if(tempPair.second==0)

zeroCounter ++;

if(tempPair.second < 0){

cout<

dataIn.close();

return false;

}

}

dataIn.close();

return true;

}

void SPI_Calculator::printYears(){

cout<

for(int i = 0; i < dataCounter; i ++)

cout<

cout<

}

void SPI_Calculator::printSPI(){

cout<

for(int i = 0; i < dataCounter; i ++){

cout<

}

cout<

}

void SPI_Calculator::calculateParameter(){

double sum = 0;

for(int i = 0; i < dataCounter; i ++)

sum += dataTable[i].second;

xAver = sum / (dataCounter-zeroCounter);

para_A = log(xAver);

double temp = 0.0;

for(int i = 0; i < dataCounter; i ++)

if((dataTable[i].second!=0))

temp += log(dataTable[i].second);

para_A -= (temp / (dataCounter-zeroCounter));

para_Gamma = (1 + sqrt(1+4*para_A/3))/ (4* para_A);

para_Beta = xAver / para_Gamma;

}

double SPI_Calculator::getSPI(int year){

double perciption;

int i = 0;

for(; i < dataCounter; i ++)

if(year == dataTable[i].first){

perciption = dataTable[i].second;

break;

}

if(i == dataCounter){

cout<

return -999;

}

double F = 0.0;

if(perciption == 0){

F=(zeroCounter / dataCounter);

}

else

F = integral(0.0000001, perciption);

double S = 0.0;

if(F > 0.5){

F = 1-F;

S = 1;

}

else

S = -1;

double t = sqrt(log(1/(F*F)));

double Z = S*(t - (c0+c1*t+c2*t*t)/(1+d1*t+d2*t*t+d3*t*t*t));

return Z;

}

double SPI_Calculator::f_probabilityDensity(double x){

double E = 2.71828;

double t_a = 1/(pow(para_Beta,para_Gamma)* f_gamma(para_Gamma,1000));

double t_b = pow(x, para_Gamma-1);

double t_c = pow(E, -x/para_Beta);

return (t_a *t_b *t_c);

}

double SPI_Calculator::f_gamma(double z, unsigned Nterms){

double g = 0.577216;// Euler-Mascheroni constant

double retVal = z*exp(g*z);

// apply products

for(unsigned n=1; n<=Nterms; ++n)

retVal *= (1 + z/n)*exp(-z/n);

retVal = 1.0/retVal;// invert

return retVal;

}

double SPI_Calculator::integral(double a,double b) {

int N = 100000*para_A*para_A;

double s = 0,h;

s=(f_probabilityDensity(a) + f_probabilityDensity(b))/2.0;

h=(b-a)/N;

for(int i=1; i

s += f_probabilityDensity(a+i*h);

return (s*h);

}

其实数学的东西实现起来没有特别复杂,两个难点在于积分(概率密度)以及 gamma 函数,在代码里也写清楚了。

使用的时候只需要按代码注释中说明的格式传入每年的降水量就行了。调用 getSPI (int year) 函数可以获取当年的 SPI。

注意,本程序基于合理的数据进行检测。不合理的数据(如每年的降水量完全相同,被视为不合理的数据)将引起意料之外的结果。

matlab中标准化降水指数程序,标准化降水指数(SPI)计算程序相关推荐

  1. 利用MATLAB中 MuPADNotebook组件将程序语言表达式转为数学表达式

    前言 在论文写作或数模竞赛中,常需要把已经在程序中列写好的方程或表达式转为数学表达式,呈现在论文或其他书面文本中,利用MATLAB中 MuPADNotebook组件可以在保证高转换准确度的同时,提高我 ...

  2. MATLAB中copula函数的程序,Copula理论MATLAB应用实例.doc

    Copula理论MATLAB应用实例.doc %-------------------------------------------------------------------------- % ...

  3. 一种MATLAB中解复杂方程(高次、指数、无解析解)的方法,可以在实现论文中公式时使用,solve函数。

    前几天我在实现一篇论文时,对于一个公式其他参数都已知的情况下,要得到剩下得那个未知的变量,由于方程的形式很复杂,用常规方法很难处理,故在实现时使用了MATLAB中solve函数,现在把方法呈现在这里, ...

  4. 在matlab中如何打开示例程序,visual studio 调用 matlab实例

    续接上篇,本文将对如何通过visual studio调用matlab画图做出指导, 并给出实例. 代码部分: 首先在头文件补充engine #include"engine.h" 然 ...

  5. matlab中累加的小程序,微信小程序学习用demo:数字累加,动态效果

    微信小程序-数字累加效果,实现方式都在注释里面,有不足之处希望老司机多多指点 num.gif (77.77 KB, 下载次数: 150) 效果图 2016-12-26 18:07 上传 1.wxml代 ...

  6. matlab中运用demod解调程序,matlab调制解调源码有代码解释原理分析

    解调程序\am\am模拟信号调制解调\am.m .............\..\..................\am_demod.m .............\..\............ ...

  7. matlab中复合中点式程序,《现代数值计算》Matlab程序整理(23页)-原创力文档

    第2 章 线性方程组的直接解法 1.1 写一个求解线性代数方程x b 的列主元素高斯消去法程序,在程序入口输入n 的 1 值,其中ij ,bj ln j ,1 i , j  n i  j  ...

  8. matlab基数排序,如何在MATLAB中编写基数排序的程序

    匿名用户 1级 2014-09-26 回答 还需要不? 追问: 需要的 追答: clc; clear all; close all; c=[72 30 83 81 5 7 46 21] sw=max( ...

  9. matlab中使用simulink标准化输出图片

    所有文章均为学习笔记,不乏有错误的地方. matlab中.m文件名不要是数字,最好是英文 当我们使用simulink仿真出如下波形后如何标准化输出 这组波形中实际上是有两个波形,分别找到两个波形的示波 ...

  10. Matlab / ArcGIS 处理GPM全球月均降水数据

    GPM降水数据网站:https://disc.gsfc.nasa.gov/datasets/GPM_3IMERGM_06/summary?keywords=GPM 这个降水数据的空间分辨率是0.1°( ...

最新文章

  1. ios 静态方法是否能被重写_小米新系统亮相,比苹果iOS更干净,21款手机支持升级...
  2. 使用Formik轻松开发更高质量的React表单(二)使用指南
  3. HDU 1525 - Euclid's Game ( 博弈 )
  4. 7-8 数字三角形 (31 分)(思路+详解+动态规划)Come Baby!!!!!!!!!!!
  5. spring mvc学习(44):springMVC运行原理
  6. InputStream 类型
  7. 学计算机必须学会模拟电路,2016年广西大学计算机与电子信息学院1304电路分析基础与模拟电子线路之电路分析基础复试笔试仿真模拟题...
  8. 多方安全计算(MPC)原理简介
  9. http2.0和http1.1的区别
  10. SqlServer数据库分离与附加
  11. mysql regexp不支持_MySQL REGEXP正则表达式
  12. PuttyPsftp
  13. 数字图像处理技术的应用领域
  14. ipad2利用crappstore安装破解软件成功-还是写一下我安装的过程吧,大家可以参考一下...
  15. Jscex没有xxxAsync().stop()怎么办?
  16. [内附完整源码和文档] 基于Android的手机音乐播放器的设计与实现
  17. 【CLAPACK函数库】CLAPACK安装与使用,编译好了出现f2c_dgemm,dgesvd_错误主要是camkelist, gcc编译库的顺序要对
  18. Ruby+Watir安装
  19. 【zabbix监控三】zabbix之部署代理服务器
  20. 【题解】洛谷P1914 小书童——密码 c++

热门文章

  1. Flash Builder 4.6(安装破解)
  2. 伺服电控领域的产业情况与各主流制造商简介
  3. 黑马python培训费用
  4. abaqus 录制结果动画_后处理动画录制
  5. linux gif录制工具,教学?演示?在Linux下安装超好用的屏幕录像机来录制gif动画...
  6. 健康管理师可以从事哪些工作
  7. fmincon函数求极值
  8. SpringBoot+Vue实现前后端分离高校学生考勤系统
  9. Excel·VBA考勤打卡记录数据整理
  10. get请求中url传参中文乱码问题