文档库 最新最全的文档下载
当前位置:文档库 › 什么是定点数,浮点数

什么是定点数,浮点数

什么是定点数和浮点数
计算机中的数除了整数之外,还有小数。如何确定小数点的位置呢?通常有两种方法:
一种是规定小数点位置固定不变,称为定点数。
另一种是小数点的位置不固定,可以浮动,称为浮点数。
在计算机中,通常是用定点数来表示整数和纯小数,分别称为定点整数和定点小数。对于既有整数部分、又有小数部分的数,一般用浮点数表示。下面分别予以介绍:
(1)定点整数:在定点数中,当小数点的位置固定在数值位最低位的右边时,就表示一个整数。请注意:小数点并不单独占1个二进制位,而是默认在最低位的右边。定点整数又分为有符号数和无符号数两类。
(2)定点小数:当小数点的位置固定在符号位与最高数值位之间时,就表示一个纯小数。因为定点数所能表示数的范围较小,常常不能满足实际问题的需要,所以要采用能表示数的范围更大的浮点数。定点就是小数点确定在第几位的.如果是整数,规定小数点在最后一位.若是小数,小数点就在第一位和第二位之间,比如0.1234e3就是定点表示的123.4.浮点就是小数点位置不确定,比如123.43,6557.521.在C语言中,一般单精度数据类型比如int,数据的范围是2的31次方,而双精度类型的整型比如long int的数据范围是2的63次方.所以双精度和单精度主要的区别在于数据的范围大小
(3)浮点数:浮点数是属于有理数中某特定子集的数的数字表示,在计算机中用以近似表示任意某个实数。具体的说,这个实数由一个整数或定点数(即尾数)乘以某个基数(计算机中通常是2)的整数次幂得到,这种表示方法类似于基数为10的科学记数法。浮点数在计算机中用以近似表示任意某个实数。浮点计算是指浮点数参与的运算,这种运算通常伴随着因为无法精确表示而进行的近似或舍入。一个浮点数a由两个数m和e来表示:a = m × be。在任意一个这样的系统中,我们选择一个基数b(记数系统的基)和精度p(即使用多少位来存储)。m(即尾数)是形如±d.ddd...ddd的p位数(每一位是一个介于0到b-1之间的整数,包括0和b-1)。如果m的第一位是非0整数,m称作规格化的。有一些描述使用一个单独的符号位(s 代表+或者-)来表示正负,这样m必须是正的。e是指数。 这种设计可以在某个固定长度的存储空间内表示定点数无法表示的更大范围的数。例如,一个指数范围为±4的4位十进制浮点数可以用来表示43210,4.321或0.0004321,但是没有足够的精度来表示432.123和43212.3(必须近似为432.1和43210)。当然,实际使用的位数通常远大于4。此外,浮点数表示法通常还包括一些特别的数值:+∞和?∞(正负无穷大)以及

NaN('Not a Number')。无穷大用于数太大而无法表示的时候,NaN则指示非法操作或者无法定义的结果。大部份计算机采用二进制(b=2)的表示方法。位(bit)是衡量浮点数所需存储空间的单位,通常为32位或64位,分别被叫作单精度和双精度。有一些计算机提供更大的浮点数,例如英特尔公司的浮点运算单元Intel8087协处理器(以及其被集成进x86处理器中的后代产品)提供80位长的浮点数,用于存储浮点运算的中间结果。还有一些系统提供128位的浮点数。
在浮点数表示法中,小数点的位置是可以浮动的。在大多数计算机中,都把尾数S定为二进制纯小数,把阶码P定为二进制定点整数。尾数S的二进制位数决定了所表示数的精度;阶码P的二进制位决定了所能表示的数的范围。为了使所表示的浮点数既精度高、又范围大,就必须合理规定浮点数的存储格式。
计算机中的所有数据都是以二进制表示的,浮点数也不例外。然而浮点数的二进制表示法却不像定点数那么简单了。先澄清一个概念,浮点数并不一定等于小数,定点数也并不一定就是整数。所谓浮点数就是小数点在逻辑上是不固定的,而定点数只能表示小数点固定的数值,具用浮点数或定点数表示某哪一种数要看用户赋予了这个数的意义是什么。
C++中的浮点数有6种,分别是:
float:单精度,32位
unsigned float:单精度无符号,32位
double:双精度,64位
unsigned double:双精度无符号,64位
long double:高双精度,80位
unsigned long double:高双精度无符号,80位(嚯,应该是C++中最长的内置类型了吧!)然而不同的编译器对它们的支持也略有不同,据我所知,很多编译器都没有按照IEEE规定的标准80位支持后两种浮点数的,大多数编译器将它们视为double,或许还有极个别的编译器将它们视为128位?!对于128位的long double我也仅是听说过,没有求证,哪位高人知道这一细节烦劳告知。下面我仅以float(带符号,单精度,32位)类型的浮点数说明C++中的浮点数是如何在内存中表示的。先讲一下基础知识,纯小数的二进制表示。(纯小数就是没有整数部分的小数,讲给小学没好好学的人)
纯小数要想用二进制表示,必须先进行规格化,即化为 1.xxxxx * ( 2 ^ n ) 的形式(“^”代表乘方,2 ^ n表示2的n次方)。对于一个纯小数D,求n的公式如下:
n = 1 + log2(D);// 纯小数求得的n必为负数
再用 D / ( 2 ^ n ) 就可以得到规格化后的小数了。接下来就是十进制到二进制的转化问题,为了更好的理解,先来看一下10进制的纯小数是怎么表示的,假设有纯小数D,它小数点后的每一位数字按顺序形成一个集合:
{k1, k2, k3, ... , kn}

那么D又可以这样表示:
D = k1 / (10 ^ 1 ) + k2 / (10 ^ 2 ) + k3 / (10 ^ 3 ) + ... + kn / (10 ^ n )
推广到二进制中,纯小数的表示法即为:
D = b1 / (2 ^ 1 ) + b2 / (2 ^ 2 ) + b3 / (2 ^ 3 ) + ... + bn / (2 ^ n )
现在问题就是怎样求得b1, b2, b3,……,bn。算法描述起来比较复杂,还是用数字来说话吧。声明一下,1 / ( 2 ^ n )这个数比较特殊,我称之为位阶值。
例如0.456,第1位,0.456小于位阶值0.5故为0;第2位,0.456大于位阶值0.25,该位为1,并将0.45减去0.25得0.206进下一位;第3位,0.206大于位阶值0.125,该位为1,并将0.206减去0.125得0.081进下一位;第4位,0.081大于0.0625,为1,并将0.081减去0.0625得0.0185进下一位;第5位0.0185小于0.03125……
最后把计算得到的足够多的1和0按位顺序组合起来,就得到了一个比较精确的用二进制表示的纯小数了,同时精度问题也就由此产生,许多数都是无法在有限的n内完全精确的表示出来的,我们只能利用更大的n值来更精确的表示这个数,这就是为什么在许多领域,程序员都更喜欢用double而不是float。
float的内存结构,我用一个带位域的结构体描述如下:
struct MYFLOAT
{
bool bSign : 1; // 符号,表示正负,1位
char cExponent : 8; // 指数,8位
unsigned long ulMantissa : 23; // 尾数,23位
};
符号就不用多说了,1表示负,0表示正
指数是以2为底的,范围是 -128 到 127,实际数据中的指数是原始指数加上127得到的,如果超过了127,则从-128开始计,其行为和X86架构的CPU处理加减法的溢出是一样的。比如:127 + 2 = -127;127 - 2 = 127
尾数都省去了第1位的1,所以在还原时要先在第一位加上1。它可能包含整数和纯小数两部分,也可能只包含其中一部分,视数字大小而定。对于带有整数部分的浮点数,其整数的表示法有两种,当整数大于十进制的16777215时使用的是科学计数法,如果小于或等于则直接采用一般的二进制表示法。科学计数法和小数的表示法是一样的。
小数部分则是直接使用科学计数法,但形式不是X * ( 10 ^ n ),而是X * ( 2 ^ n )。拆开来看。
0000000000000000000000000000000
符号位指数位尾数位
双精度浮点数和单精度浮点数
这两者主要在精度上有区别。
双精度浮点数能精确表示 1.79769313486231570E+308 到 -4.94065645841246544E-324 范围的负数和从 4.94065645841246544E-324 到 1.79769313486231570E+308 范围的正数。
单精度浮点数能够精确表示从 -3.4028235E+38 到 -1.401298E-45 的负数和从 1.401298E-45 到 3.4028235E+38 的正数。
单精度浮点数的精度没有双精度那么高,但是所需内存少,运算速度快。
提示
如果对精度要求不高,则应该尽量避免使用双精度浮点数,而应该使用单精度浮点数。这一点在一

些大型应用程序中非常重要。如果在定义变量时,单精度浮点数就足够了,但是却使用了双精度浮点数,会大大减慢程序的运行。
如果某个变量只需要整数类型就足够了,应避免用浮点数。因为整数的运算速度更快。
浮点数转换成十进制数的步骤
该步骤与前面“十进制数转换成浮点数”的步骤是互逆的,其具体步骤如下:
1、分割数字的符号、阶码和有效数字;
2、将偏移阶码减去偏移,得到真正的阶码;
3、把数字写成规格化的二进制数形式;
4、把规格化的二进制数改变成非规格化的二进制数;
5、把非规格化的二进制数转换成十进制数。
例11.2 把协处理器中的浮点数1100000111001001000000000000转换成十进制数

1、把浮点数1100000111001001000000000000分割成三部分,可得:
符号位是1,阶码是10000011,尾数是1001001000000000000
2、还原阶码:10000011 – 01111111=100
3、该浮点数的规格化形式:1.1001001×24 (其中前面的“1.”从隐含位而来)
4、该浮点数的非规格化形式:11001.001
5、该浮点数的十进制数为-25.125 (因为符号位为1,所以,该数是负数)

下面是学习和掌握十进制数转化为浮点数的控件,它可按步骤演示整个转换过程。

三、浮点数说明形式
在汇编语言中,可用DD、DQ和DT来分别说明单精度、双精度和扩展精度的浮点数。
在MASM 6.0系统中,正浮点数前面不能书写‘+’,但MASM 6.11系统更正了这种错误,并提供了新的浮点数说明方法,即:可用REAL4、REAL8和REAL10来分别代替DD、DQ和DT。
在定义浮点数时,要使用伪指令.8087、.287或.387等。
例如:
.387
data1DD123, -543;定义单精度浮点数
data2REAL43.345E+3;定义单精度浮点数
data3REAL8321.545;定义双精度浮点数
data4REAL10254.555;定义扩展精度浮点数
浮点数转换到16进制字符串
这几天一直在弄postgre的数据写入,特别是几何数据的写入。在几何数据的写入过程中,可以有多种
通过WKB,TEXT都是可以的。先觉得,通过Text建立会比较慢,因为要用到geometryfromtext,与把数据转换成文本再让数据库进行转换,不如自己进行转换成 WKB形式的
第一段的难点就是将double类型转换成十六进制字符串,就是将64bit转换成16进制字符串表示。首先学习了IEEE754标准,了解浮点函数的编码方式。
void TestDouble(double value)
...{
int count=0;
string x;
if (value>0)
...{
x+="0"; //判断符号
}
else
...{
x+="1";
value=-value;
}
while (2<=value) //获得小数点后值
...{
value=value/2.0;
count++;
}
count=count+1023;

//将阶码变成二进制表示
bitset<11>code(count);
x+=code.to_string(); //前半部分二进制表示
int digit=-1;
value-=1.0;
//////////////////////////////////////////////////////////////////////////将数值用二进制表示/////
double posval=0.0;
double tempval=0.0;
while (value!=0&&digit>-54)
...{
posval=Power(2,digit);
tempval=value-posval;
if(tempval>0)
...{
x+="1";
value=tempval;
}
else if (tempval==0)
...{
x+="1";
break;
}
else
x+="0";
--digit;
}
int size=64-x.size();
if (size>0)
...{
char* temp=new char[size];
memset(temp,'0',size);
x.append(temp,size);
delete temp;
}
cout<}

static string binTohexstr(string temp)
...{
string value="";
if (temp.size()%4!=0)
...{
return NULL;
}
while ((temp.size()-4)>0)
...{
value+=binTohex(temp.substr(0,4));
temp=temp.substr(4,temp.size()-4);
}
value+=binTohex(temp);
return value;
}

static char binTohex(string temp)
...{
if("0000"==temp)
return '0';

else if("0001"==temp)
return '1';

else if("0010"==temp)
return '2';

else if ("0011"==temp)
return '3';

else if("0100"==temp)
return '4';

else if("0101"==temp)
return '5';

else if("0110"==temp)
return '6';

else if("0111"==temp)
return '7';

else if("1000"==temp)
return '8';

else if("1001"==temp)
return '9';

else if("1010"==temp)
return 'A';

else if("1011"==temp)
return 'B';

else if("1100"==temp)
return 'C';

else if("1101"==temp)
return 'D';

else if("1110"==temp)
return 'E';

else if("1111"==temp)
return 'F';

else
return 'G';
}
上面是整个转换到流程,先转换成二进制,难点在于理解double值得表示方式为value=(1+m)*2n其中2n表示2的n次方。首先求出2的阶码,double的阶吗有12位,就是2048次方,但是double还有表示小数后的值,所以要表示-1023~1024的值,就要进行转换。得到的值都是需要进行移位,3.5=(1+0.75)×2;所以阶吗就是1+1023=1024,就是10000000。另外double 的第一位是符号位,0是正,1是负。(1+m)中的M是大于0小于1的。这个M是value不断被2除得到大于1小于2的数字,又因为double里面的数都是默认加个1,所有得到m。
m再用小数表示,得到结果
请教一个浮点数转换成定点数的问题!
输入是一个24位的ieee754标准的浮点数,格式是1_8_15,已经直接去掉了最后8位, 如何把它转换

成格式为 1_22_8 的定点数? (定点数 整数22位,小数8位)

因为用的 design ware, 有个模块叫 "flt2i", 可以把浮点数换成整数, 但是小数部分怎么办呢? 不能用别的浮点运算器.

苦闷了好几天了,请教各位~~~~
回答区:
1、根据IEEE 745: 如 11 = 8 + 2 + 1 = 1011b = 1.011x2^3
step 1: 1_00000101_1110_0000_0000_000
step 2: 1_10000010_0110_0000_0000_000 说明:此时将Exponent做127的offset,同时将整数位的1省略掉只剩下Fraction。

所以在做浮点数到定点数的变化时,首先将8it Exponent减掉offset(127),然后将 15bit Fraction 补足整数位1
然后根据定点数和浮点数的差值,对 Fraction 做位移运算。。不足位补“0”。
2、IEEE754标准在表示浮点数时,每个浮点数均由三部分组成:符号位S (sign),指数部分E (exponent) 和尾数部分M (mantissa)。

浮点数一般采用以下四种基本格式:

(1)单精度格式(32位):除去符号位1位后,E占8位,M占23位。

(2)扩展单精度格式:E>=11位,M>31位。

(3)双精度格式:(64位);E=11位,M=52位。

(4)扩展双精度格式:E>=15位,M>63位。

我们最重要的是掌握单精度格式的表示法。在IEEE754标准中,约定小数点左边隐含有一位,通常这位数就是1,这样实际上使尾数的有效位数为24位,即尾数为1.M。指数的值在这里称为阶码,为了表示指数的正负,所以阶码部分采用移码表示,移码值为127,阶码值即从1到254变为-126至+127,在 IEEE754中所有的数字位都得到了使用,明确地表示了无穷大和0,并且还引进了"非规格化数" denormalized numbers (also called subnormal numbers)
,使得绝对值较小的数得到更准确表示。请看下表:

S(1位) E(8位) M(23位) N(32位)
符 0 0 (-1)S·2E-127·(1.M) 为规格化数
0 不等于0 (-1)S·2-126·(0.M) 为非规格化数
号 1到254之间 不等于0 (-1)S·2E-127·(1.M) 为规格化数
255 不等于0 NaN(非数值)
位 255 0 无穷大

其中红色字0、1表示隐含位,注意当数字N为非规格化数或是0时,隐含位是0。

以单精度为例子,我们知道指数有 8 位,可以表示 2^8=256 (0, 1, 2, ..., 255) 个数,但是最小的 e_min =-126, 最大e_max = 127, 只有 127+126+1=254 个数, 另外两个数用来干什么呢?
用来表示零和无穷大,请参考下面的表. 当 e = e_min -1 时,用来表示零,(零还有正负之分);
当 e=e_max +1 时, 用来表示正负无穷大。 为什么零不是真正的零呢?因为 IEEE 754 标准约定小数点左边隐含有一位,而且这隐含的一位的数值对于规格数而言是1

,对于非规格数而言是0.
看起来双精度浮点数的范围很大,但是 171 的阶乘约是 1.24E10^309 已经比双精度能表示的最大的浮点数大。

The largest number that can be represented is approximately 2.0 · 2127 ≈ 3.4028 × 10^38 in single precision and 2.0 · 21023 ≈1.7977 × 10^308 in double precision. The smallest normalized number is 1.0 · 2?126 ≈1.1755 × 10^ ?38 in single precision and 1.0 · 2^?1022 ≈ 2.2251 × 10^?308 in double
precision.

Unit roundoff error : 1 和某个数相加用浮点数表示还等于1, 则这个数称位 Unit roundoff error.
Unit roundoff error 是 2^?24 ≈ 5.96 · 10^?8 , in single precision;
2^?53 ≈ 1.11 · 10^?16 in double precision.
IEEE 754标准在表示浮点数时,每个浮点数均由三部分组成:符号位S,指数部分E和尾数部分M.S=0表示正数,S=1表示负数.
浮点数一般采用以下四种基本格式:
单精度格式(32位):除去符号为1位后,E占8位,M占23位.
扩展单精度格式:E>=11位,M=31位
双精度格式 64位):E>=11位,M=52位.
扩展双精度格式:E>=15位,M>63位.
在IEEE 745标准中,约定小数点左边隐含有一位,通常这次数就是1,这样实际上使尾数的有效位数为24位,即尾数为1.M.指数的值在这里称为阶码,为了表示指数的正负,所以阶码部分采用移码表示,移码值为127(注意这是IEEE 754指定的单精度的偏移量,而不是指移码的偏移量为128),阶码值即从1到254变为-126至-126至127,在IEEE 754中所有的数字位都得到了使用.
(1)0.15625转换成二进制值为0.00101
在IEEE 754中规格化表示为1.01X2^(-3)(这里的-3表示小数点向右移动了3位),所以e=127+(-3)=124
IEEE 754编码为:0 01111100 01000000000000000000000
(2)-5转换成二进制值为-101
在IEEE 754中规格化表示为1.01X2^2,e=127+2=129
IEEE 754编码为: 1 10000001 0100000000000000000000

说明:这里的尾数是指0.1X2^M次方,即为所用格式的M的位数,eg:单精度格式中M占23位,得出结构中0.1X2^23次方化成二进制数为0100000000000000000000
怎样把浮点数转换成字符串?
怎样把浮点数转换成字符串?
自带的函数itoa,ltoa都是转换整数的,遇到浮点数,双精度的数怎么办?
回答区:
1、char * _fcvt(double value,int dount,int *dec,int *sign);
说明:
value 为要被转换的数值
count 为小数点后的位数
dec 为小数点所在位置
sign 为正负号,0代表正,非0整数代表负

#include
#include
void main()
{
int dec,sign;
char *temp;
//double value=0.1256;
double value=-0.01256;
temp=_fcvt(value,3,&dec,&sign);
printf("String after convert :%s\n",temp);
printf("Decimal :%d\n",dec);
printf("sign :%d\n",sign);
}
2、在将浮点型数字转换为字符串时,需要使用另外一组函数。
以下是用fcvt()函数将浮点型值转换为字符串的一个例子:
# include
# include

. h>
void main (void);
void main (void)
{
double num = 12345.678;
char * sir;
int dec_pl, sign, ndigits = 3; /* Keep 3 digits of precision. * /
str = fcvt(num, ndigits, &dec-pl, &sign); /* Convertthe float to a string. * /
printf("Original number; %f\n" , num) ; /* Print the original floating-point value. * /
printf ("Converted string; %s\n",str); /* Print the converted string'svalue. * /
printf ("Decimal place: %d\n" , dec-pi) ; /* Printthe location of the decimal point. * /
printf ("Sign: %d\n" , sign) ; /* Printthe sign.0 =positive,1 =negative. * /
}
fcvt()函数和itoa()函数有数大的差别。fcvt()函数有4个参数:第一个参数是要转换的浮点型值;第二个参数是转换结果中十进制小数点右侧的位数;第三个参数是指向一个整数的指针,该整数用来返回转换结果中十进制小数点的位置;第四个参数也是指向一个整数的指针,该整数用来返回转换结果的符号(0对应于正值,1对应于负值)。需要注意的是,fcvt()函数的转换结果中并不真正包含十进制小数点,为此,fcvt()函数返回在转换结果中十进制小数点应该占据的位置。在上例中,整型变量dec_pl的结果值为5,因为在转换结果中十进制小数点应该位于第5位后面。如果你要求转换结果中包含十进制小数点,你可以使用gcvt()函数(见下表)。下列函数可以将浮点型值转换为字符串:
---------------------------------------------------------
----------------
函数名作用
---------------------------------------------------------
----------------
ecvt() 将双精度浮点型值转换为字符串,转换结果中不
包含十进制小数点
fcvt() 以指定位数为转换精度,余同ecvt()
gcvt() 将双精度浮点型值转换为字符串,转换结果中包
含十进制小数点
---------------------------------------------------------
}

相关文档
相关文档 最新文档