Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1240386
  • 博文数量: 124
  • 博客积分: 7074
  • 博客等级: 少将
  • 技术积分: 1336
  • 用 户 组: 普通用户
  • 注册时间: 2007-03-15 16:37
文章分类
文章存档

2011年(3)

2010年(18)

2009年(8)

2008年(14)

2007年(81)

分类: C/C++

2007-07-23 14:20:36


数据标准化/归一化方法
=====================
归一化方法(Normalization Method)
1.把数变为(0,1)之间的小数
   主要是为了数据处理方便提出来的,把数据映射到0~1范围之内处理,更加便捷快速,应该归到数字信号处理范畴之内。
2.把有量纲表达式变为无量纲表达式
   归一化是一种简化计算的方式,即将有量纲的表达式,经过变换,化为无量纲的表达式,成为纯量。比如,复数阻抗可以归一化书写:Z = R + jωL = R(1 + jωL/R) ,复数部分变成了纯数量了,没有量纲。另外,微波之中也就是电路分析、信号系统、电磁波传输等,有很多运算都可以如此处理,既保证了运算的便捷,又能凸现出物理量的本质含义。
 
标准化方法(Normalization Method)
   数据的标准化是将数据按比例缩放,使之落入一个小的特定区间。由于信用指标体系的各个指标度量单位是不同的,为了能够将指标参与评价计算,需要对指标进行规范化处理,通过函数变换将其数值映射到某个数值区间。一般常用的有以下几种方法。
(1) 最小-最大规范化对原始数据进行线性变换。假定MaxA与MinA分别表示属性A的最大与最小值。最小最大规范化通过计算将属性A的值映射到区间[a, b]上的v。一般来说,将最小-最大规范化在用于信用指标数据上,常用的有以下两种函数形式:
  a) 效益型指标(越大越好型)的隶属函数:
  b) 成本型指标(越小越好型)的隶属函数:
(2) z-score规范化也称零-均值规范化。属性A的值是基于A的平均值与标准差规范化,A的值计算公式
(3) 小数定标规范化是通过移动属性A的小数点位置来实现的。小数点的移动位数依赖于A的最大绝对值,计算公式为 其中,j是使得MAX(|v|)<1的最小整数。例如A的值为125,那么|A|=125,则j=3,有v=0.125。
///////////////////////////////////////////////////////////////////////////////////
//C++实现的归一化和反归一化处理函数
///////////////////////////////////////////////////////////////////////////////////
void __fastcall TModelManage::TranslateData(TModel* pModel,int Id,double *Value,int Flag)
{
  //转换函数类型
  int iChgFunc;
  //节点对应的最大、最小值
  double dMaxValue,dMinValue;
  //取节点配置信息:转换函数类型,最大值,最小值
  GetNodeConfValue(pModel->ConfTable,Id,&iChgFunc,&dMaxValue,&dMinValue);
  if(Flag==1)               //仿真时不取边界值,以避免仿真结果误差太大
  {
    if(*Value<=(dMinValue*1.005))
        *Value=dMinValue*1.005;
    if(*Value>=(dMaxValue*0.995))
        *Value=dMaxValue*0.995;
  }
  else
  {
    if(*Value<=dMinValue)
        *Value=dMinValue;
    if(*Value>=dMaxValue)
        *Value=dMaxValue;
  }
  //线性函数转换,转换在0-1之内
  if(iChgFunc==0)
  {
    *Value=(*Value-dMinValue)/(dMaxValue-dMinValue);
  }
  //用atan函数转换在0-1之内
  else if(iChgFunc==2)
  {
    *Value=atan(*Value)*2/M_PI;
  }
  //用log函数转换
  else if(iChgFunc==1)
  {
    if(*Value<=1)
        *Value=0;
    else
        *Value=log10(*Value); //用log10函数转换(缩小)
    if(dMaxValue>1)
        *Value=*Value/log10(dMaxValue); //转换为0-1之间
  }
  //不用转换
  else if(iChgFunc==3)
  {
      *Value=*Value;
  }
  *Value=((0.5-0.001)/0.5)*(*Value)+0.001;   //用线性函数把数据转换为0.001-0.0.9995之间
}
///////////////////////////////////////////////////////////////////////////////////
//反数据转换,主要是针对仿真结果要反算回实际预测的值
void __fastcall TModelManage::UnTranslateData(TModel* pModel,int Id,double *Value,int Flag)
{
  //转换函数类型
  int iChgFunc;
  //节点对应的最大、最小值
  double dMaxValue,dMinValue;
  //取节点配置信息:转换函数类型,最大值,最小值
  GetNodeConfValue(pModel->ConfTable,Id,&iChgFunc,&dMaxValue,&dMinValue);
  *Value=(((*Value)-0.001)*0.5)/(0.5-0.001);     //对应于---->用线性函数把数据转换为0.001-0.0.9995之间
  //反线性函数转换
  if(iChgFunc==0)
  {
    *Value=(*Value)*(dMaxValue-dMinValue)+dMinValue;
  }
  //用tan函数转换
  else if(iChgFunc==2)
  {
    *Value=tan(*Value)*M_PI/2;
  }
  //用反log函数转换
  else if(iChgFunc==1)
  {
    *Value=pow(10,(*Value)); //用反对数方式函数转换(放大)
  }
  else if(iChgFunc==3)
  {
    *Value=*Value; //不用转换
  }  
}
///////////////////////////////////////////////////////////////////////////////////
 
数据类型相互转换
=============
这种转换可能发生在算术表达式、赋值表达式和输出时。转换的方式有两种:自动转换和强制转换。

自动转换
========
自动转换由编译系统自动完成,可以将一种数据类型的数据转换为另外一种数据类型的数据。
1)算术运算中的数据转换
如果一个运算符有两个不同类型的运算分量,C语言在计算该表达式时会自动转换为同一种数据类型以便进行运算。先将较低类型的数据提升为较高的类型,从而使两者的数据类型一致(但数值不变),然后再进行计算,其结果是较高类型的数据。 自动转换遵循原则——“类型提升”:转换按数据类型提升(由低向高)的方向进行,以保证不降低精度。 数据类型的高低是根据其类型所占空间的大小来判定,占用空间越大,类型越高。反之越低。 例如:算术运算x+y,如果x和y的类型都是int型变量,则x+y的结果自然是int型。如果x是short型而y是int型,则需要首先将x转换为int型,然后再与y进行加法计算,表达式的结果为int型。
2)赋值运算的类型转换
在执行赋值运算时,如果赋值运算符两侧的数据类型不同,赋值号右侧表达式类型的数据将转换为赋值号左侧变量的类型。转换原则是:当赋值运算符“=”右侧表达式的值被计算出来后,不论是什么类型都一律转换为“=”左侧的变量的类型,然后再赋值给左侧的变量。
例如:float a;
a=10;? /*结果为a=10.0(数据填充)*/
int a;
a=15.5 /* 结果为a=15(数据截取)*/
在赋值类型转换时要注意数值的范围不能溢出。既要在该数据类型允许的范围内。如如果右侧变量数据类型长度比左侧的长时,将丢失一部分数据,从而造成数据精度的降低。
3)数据输出时的类型转换
在输出时,数据将转换为格式控制符所要求的类型。同样可能发生数据丢失或溢出。类型转换的实际情况是:字符型到整型是取字符的ASCII码值;整型到字符型只是取其低8位;实型到整型要去掉小数部分;整型到实型数值不变,但以实数形式存放;双精度到实型是四舍五入的。
 
强制转换
========
一般情况下,数据类型的转换通常是由编译系统自动进行的,不需要程序员人工编写程序干预,所以又被称为隐式类型转换。但如果程序要求一定将某一类型的数据从该种类型强制地转换为另外一种类型,则需要人工编程进行强制类型转换,也称为显式转换。强制类型转换的目地是使数据类型发生改变,从而使不同类型的数据之间的运算能够进行下去。
语法格式如下:
(类型说明符)表达式
功能是强行地将表达式的类型转换为括号内要求的类型。
例如:(int)4.2的结果是4;
又如:int x;
(float)x;x的值被强制转换为实型,但是并不改变的x类型是整型。只是在参与运算处理时按照实型处理。
-----------------------------------------------------------------------------------

C#支持隐式类型转换。意思是如果我们试图给变量x赋予变量y的值:
x = y;
且这两个变量被声明为不同类型,则C#仍将尝试赋值操作,自动把y的类型转换为x的数据类型,前提是不能损失数据精度。(C#与C和C++不同的是,后两者即便损失精度也会做自动转换)。举例说明:
  int x;
  double y;
  y = 2.7;
  x = y; // 试图将double值赋给int变量,只在C和C++中有效,C#不支持。
这段代码中,我们试图把y的双精度值2.7复制给x,而x是一个整类型变量。假使赋值操作真被执行,则y值的小数部分将被截去,x得到值2。这样就发生了精度损失,或称窄化转换(narrowing conversion)。C或C++编译器允许这样的赋值,不出一声就把值截;然而,C#编译器不会认为这是我们的真意,而是在最末行产生一个错误。error CS0029: Cannot implicitly convert‘double’to type‘int’
为了明确告诉C#编译器我们愿意接受精度损失,必须进行显式转换,把表达式值转换为括号里的目标类型。
换言之,我们需要重写上例的末行,让C#编译器接受它:
  int x;
  double y;
  y = 2.7;
  x = (int) y;                 // 能够编译。C#编译器“松了口气”。
                                 // 因为我们明确地告诉它,
                                 // 想要进行窄化转换。
当然,如果我们进行反向赋值:
  int x;
  double y;
  x = 2;
  y = x;                        // 把int值赋给double变量;
                                 //y的值将是2.0。
C#编译器不会对末行产生问题,因为在该个案里,我们把较低精度的值——2——赋予了拥有较高精度的变量。这称作宽化转换(widening conversion);这类转换在C#中会自动进行,无需显式转换。
注意,在C#里面给float变量赋值时,有一种特殊情况;语句
float y = 3.5;  // 不会被编译!
将产生一个编译器错误,因为类似3.5这样带有小数部分的数字常量会被C#认为是拥有更高精度的double值,所以编译器将因精度损失而拒绝执行。要进行这样的赋值,必须显式地把浮点常量转换为float值:
float y = (float) 3.5;  // 没问题;进行了转换。
或者,也可以使用后缀F,强制编译器把赋值语句右边的常量看作浮点值:
float y = 3.5F;  // 可以,我们指示了该常量
                    // 应被当作浮点值处理。
还有一种选择是直接使用double变量而不用float变量来表示浮点数。在SRS应用中,无论何时要声明浮点变量,我们都会使用double来代替,这样可以避免类型转换操作。
仅有一种C#简单类型不可转换到另一类型,无论显式或隐式都不行,那就是bool类型。
你将在本书稍后部分看到其他和对象相关的转换。
 
阅读(14643) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~