你所在位置:首页C#.net开发 → 详解C#的数学类,Math,浮点数(上)

详解C#的数学类,Math,浮点数(上)

发布时间:2019-07-11

C#语言支持表B-1所示的11种数值类型,分别为整数,浮点数和小数。

\

在一个程序中,整数(没有小数点的数)被认为是一个int类型(除非其值大于最大的int值),根据数据值,该数据依次被视为uint,long,ulong,带小数点的数被认为是一个double值。这就是说(1.0).GetType()==typeof(double).

你可以在数字说明上使用前缀来表明自己的意图。

\

其中u代表无符号的意思。因为无符号,所以u代表了数据是正数或0,不可能是负数。

 

A:检查整数溢出

考虑下面的代码:

short s=32767;s+=1;

ushort us=0;us-=1;

在第一种情况下,一个有符号的数加1,经过其最大值,由于整数在内存中存储方式的原因,结果是-32768.

在第二种情况下,一个无符号的数被减为小于0,结果将是65535.

在这两道例子中,分别出现了上溢和下溢的情况,如果想避免这种情况的发生,可以使用checked关键字,

或者使用下面的编译器开关:

/checked+

默认编译器开关对应为:/checked-

如果使用checked关键字:

short s=32767;

checked

{

  s+=1; //将产生一个OverFlowException.

}

 

迄今为止,我一直都在独自介绍运行时的整数向上或向下溢出检查,在默认情况下编译器会将编译时的向上和向下溢出标记为一个错误,而和你的编译器开关无关。

 

例如语句short s=32767+1;

会产生一个编译时错误,因为在编译期间对加法进行求值.

例如下面的例子:

const int i1=65536;

const int i2=65536;

int i3=i1*i2;

因为i1,i2都是const值,所以编译器在编译的时候会尝试对i3=i1*i2进行求值,并遇到一个向上溢出。所以会导致编译错误。

编译器开关不会覆盖这一行为,但是unchecked关键字可以覆盖这种行为。

int i3=unchecked(i1*i2).可以正常编译.

 

B:小数类型 

decimal 关键字表示 128 位数据类型。同浮点型相比,decimal 类型具有更高的精度和更小的范围,这使它适合于财务和货币计算。decimal 类型的大致范围和精度如下表所示。

它使用16字节(128位)存储每一个值。128位被划分为96位整数位,一个符号位,以及一个可以在0~28之间变化的比例因子。在数学上,这个比例因子是一个10的负指数幂,表示数值中小数点位置的编号。

例如,如果一个小数定义等于12.34,那么这个数的存储方式是整数0x4D2(或1234),以及一个比例因子2,

 

只要一个小数具有(或小于)28个有效数字以及(或小于)28个小数位置,decimal数据类型就可以准确的存储它。对于浮点数而言,这是不成立的!,如果定义一个float值等于12.34,那么它会被存储为0xC570A4(或12939428)除以0x100000(或1048576),这个值等于12.340000152587890625 约等于12.34。即使您将一个double值定义为等于12.34,它也是被存储为:0x18AE147AE147AE(或6 946 802 425 218 990)除以0x2000000(或562 949 953 421 312),它也只是约等于12.34.

 

这就是你在不想让美分神秘的出现和消失的地方执行计算时应该使用decimal的原因,因为浮点数不精确。

浮点数据类型在科学和工程应用方面很合适,但不是金融应用所期望的。

 

Decimal的构造函数(节选)

Decimal(int iLow,int iMiddle,int iHigh,bool bNegative,byte byScale)

例如表达式:new Decimal(123456789,0,0,false,5)

创建了一个decimal类型的小数:1234.56789.,

5代表小数点从左边开始往右边开始算。移动5位。

如果最后一个参数为1,则为12345678.9.

最后一个参数为2,则为1234567.89.

最后一个参数为3,则为123456.789

...

 小数正值的最大值是:new Decimal(-1,-1,-1,false,0) ==Decimal.MaxValue.

接近0的最小Decimal值是:new Decimal(1,0,0,false,28)==0.0000000000000000000000000001==1*10-28.

如果在C#程序中将这个数除以2,那么结果将是0.

在上面我已经指出浮点表示法为什么经常是近似值。当你开始在浮点数上执行算术运算时,近似情况可能更严重。

例如,几乎每一个使用浮点数的人都很清楚的知道,应该存储为4.55的数经常被存储为4.549999或4.550001.

小数表示的情况要好很多,例如假设m1被定义为

decimal m1=12.34

在内部m1有一个整数部分1234和一个比例因子2,同时假设m2被定义为

decimal m2=56.789;

整数部分是56789,比例因子为3,现在将两个数相加:

decimal m3=m1+m2;

在内部,m1的整数部分被乘以10(得到12340),比例因子被设置为3.现在整数部分直接相加:12340+56789等于69129,比例因子为3,实际值是69.129.每一个数都是准确的。

现在将这两个数相乘:

decimal m4=m1*m2;

在内部,两个整数部分相乘(1234*56789等于70 077 626),比例因子相加(2+3等于5)。实际的数值结果为:70.077626。这一次,计算也是准确的。

在相除时....哦,My god,除法是杂乱的,无论你怎样去做都是如此,但是对于大多数情况而言,使用Decimal你可以更好的控制结果的精度和准确度.

 


上一篇:详解C#的数学类,Math,浮点数(中)
下一篇:volatile