_dspinth 可以转换大于1的ieee754浮点数转换吗

2144人阅读
CC++Design(40)
文件编码IO(24)
// 本文不完全是原创,只是整合了一些知识和观点和自己的测试代码,对与错仅供参考。
& 计算空间几何变换和动画中经常使用的浮点数宏符号的含义:
float fSValue = 1.0e-07;//等于1.0e-07,1.00e-07,1e-7,等价于1.0 * 10^-7
&& float fValue = -1.0e-7;// -1.0e-7等价于-1.0 * 10 ^-7
&&& const double EPSILON = 1.00e-07;
&& &const float&& FLT_EPSILON& = 1.e-07F;
&& &const double& DBL_EPSILON = 2.;
// 计算机底层数字转换:
&&& //1.10进制转换为n进制,正数除以进制,倒转取余(通过16进制和2进制转换更方便);小数乘以进制数,顺序取整。
&& &//2.N进制数转换为10进制数,Ax(2^1) + Bx(2 ^0) + Cx(2^-1)数列形式表示,无论正数负数都一样。
&& &//3.浮点数表示:符号位,指数位(0-127表示负数,(127-256)表示正数),尾数(去掉前面一位)。
&& &//4.大于1Byte的数字和非数值类型,都要进行小端模式排序存放(对于一个单位结构转换后才能得到正确的值)。
// 整数是直接转换为16进制表示(存储转换为小端模式存储),浮点数需要按照转换公式和特殊公式处理(存储转换为小端模式存储),
// 非数值数据,例如ASCII字符,Unicode会转换为相应的字节代码,或者双字节代码来代替;二进制非数值数据存储, 都可以转换为ASCII,UTF-8表示,
// 会索引到文字的图形贴图或者计算的像素。汉字Ascii为负数,那是解析错误,因为汉字有自己的编码,但是存储和显示出来都是对的。
// 图形数据,颜色像素数据,可以用unsigned int表示,32位,每字节表示一个颜色值,将图形数据提交到显卡,显卡会映射为对应的颜色值。
// 1.浮点数的表示
//小数的处理: &
//0.4=0.5*0+0.25*1+0.125*1+0.;…… &
//实际上这永远算不完!这就是著名的浮点数精度问题。
& //1)浮点数表示为十六进制数
// 公式:将浮点数化为:Sx(2^E)xF 后转换为:(-1)Sx(2^(E + 127))x(F - 1),得到S+(E+127)+(F-1)的二进制数,也就是十六进制数。
// 浮点数表示格式:float:符号位(1) 指数位(8) 尾数位(23); double:也是类似的方式,只是位数不同。
// 对于64位的浮点数,最高的1位是符号位S,接着的11位是指数E,剩下的52位为有效数字F。
// 符号位为0则是正数,1则是负数。
//指数位需有负数不用[-128,127]而用[0,255]表示,负数在[0,127],正数在[128,255]
//尾数的前面都是1.1000,因为没有0.11000,故前面可以省略1
// 特殊情况公式转变(表示正负0或者比2^(-127)更小的小数):当用上面的的公式转换后发现:二进制科学计数法得到真实的 E &= -127,那么转换为十六进制时取0x00; F变为0.xxx形式,首位为0舍去,
// 后面的位数为xxx,符号位还是S.
/*转换函数
& string DigitalData::TestFloat(float fData)
& unsigned char *pData = (unsigned char*)&fD
& char szBuffer[32];
& //再转化为16进制为:47 F1 20 00,最后把它翻过来,就成了:00 20 F1 47。
& unsigned char Tail = *(pData);
& unsigned char Tail2 = *(pData + 1);
& unsigned char Exp = *(pData + 2);
& unsigned char Head = *(pData + 3);
& sprintf_s(szBuffer, &%02x%02x%02x%02x&, Head, Exp,Tail2, Tail);
& //printf(szBuffer);
& return string(szBuffer);
/*例子1:f表示为:00000.0左移16位后变为:
&& & 1.00000 * ( 2 ^ 16 )
&& &符号位:0
&& &指数:16为正数,加上127为:143二进制为
&& &尾数:1.00000去掉首位变为:0.00000,尾数二进制为:00000 不足23位在后面补足
&& &那么我们按照前面讲的格式把它拼起来:
&& &再转化为16进制为:47 F1 20 00,最后把它翻过来,就成了:00 20 F1 47。
&& &例子2: 123.456f 正数部分表示为:1111011 x (2 ^0), 小数部分(乘2取整)表示为:0.01 1000 1 x (2 ^ 0)
&& &合并起来:1.01 1 x (2 ^ 6).
&&& 符号位:0(1位), 指数位是127 + 6:位),尾数部分(去掉前面的1)是:01 1(23位)
&& &转换为16进制是: 42 F6 E8 31 小端模式翻转过来是:31 E8 F6 42 由于乘法精度问题可能不准确
&& &例子3:纯小数模式:0.0456f,转换为二进制小数是:0 x (2 ^ -1)
&& &化为科学计数法格式约为:1.0111101 x (2 ^ -5)。
&& &符号位:0 ,指数位(127 -5 = 122): ,尾数(去掉前面一位约为):
&& &二进制为:11 1010
&& &转换为16进制:3D 3A ,小端翻转后约为:3A 3D
&& &准确的数字为:
&& &123.5f的二进制为: x (2 ^0)等于1.1110111 x (2 ^6)
&& &符号位为:0 ;指数位为:127 + 6 = 133 为;小数位去掉首位为:1110111
&& &最终二进制为:11 0
十六进制为:42F70000 反转存储为:.
&& &同理:
&& &1.5f二进制为:1.1 x (2 ^0)
&& &符号位:0 ;指数位为:127 + 0 = 127 等于;小数位为:0
&& &最终二进制为:00
十六进制为:3FC00000 小端存储为:0000C03F
&& &0.15625的十六进制为:3e200000,存储小端为:0000203e
&& &0.5为:十六进制为:3F000000
&& &2)十六进制数转换为浮点数
&& &符号位S需要注意正负,2的指数位E需要减去127得到真正的指数位,小数位F需要前面忽略的1得到真正的小数位(特殊情况例外).
&& &公式:浮点数十六进制数抽取S/E/F出来后,组装为:(-1)Sx(2^(E - 127))x(F + 1)的小数,也就是表示的浮点数。
&& &特殊情况:
&& &若E位为0并且F位也为0时表示浮点数0,此时浮点数受S位影响,表现出+0和-0两种0,但数值是相等的。
&& &比如二进制数0x表示+0,二进制数0x表示-0,其中中的1为符号位。
&&& 特殊情况公式转变(表示正负0或者比2^(-127)更小的小数):当用上面的的公式转换后发现:二进制科学计数法得到真实的 E &= -127,那么转换为十六进制时取E为0x00; F变为0.xxx形式,首位为0舍去, 后面的位数为xxx,符号位还是S.
&& &若E为0,且F不为0时,那么这时表示的是比1.0 x 2(^-127)更小的数;这个时候S为正负,E为1-127等于-126(因为后面会加上0.使得变小了所以-127变为-126变大一位),
&& &F取得后面的数xxxx前面加上0.得0.xxxx
&& &例如:
&& &将0x拆分,得到第一位符号位s=0,后面8位的指数E=,最后23位的有效数字M=000 00 。
&& &由于指数E全为0,所以符合上一节的第二种情况。因此,浮点数V就写成:
&& &V=(-1)^0×0.×2^(-126)=1.001×2^(-146)
&& &显然,V是一个很小的接近于0的正数,所以用十进制小数表示就是0.000000
&&& 若E位为255并且F位为0时表示无穷大的数,此时浮点数受S位影响,例如0x7F800000表示正无穷大,0xFF800000表示负无穷大。当我们使用1个数除以0时,结果将被记作0x7F800000。无穷大的调试表示为:1.#INF,当除以0的时候会发生。INF是infinity 无穷大的意思。
&&& 若E位为255并且F位不为0时表示非数值,也就是说是非法数,例如0x7F800001。非法数的调试表示为:1.#IND, 对负数开平方,对负数取对数,0.0/0.0,0.0*∞, ∞/∞ 等会产生。或者表示为NAN。IND是indeterminate不确定/模糊的意思,NAN是not a number的意思。
&& &函数:
&& &// 3F000000
&& &float DigitalData::GetFloatFromString( string &strFloatValue)
&& &float fV
&& &char szBuffer[4];
&& &}tempU
&& &// 十六进制字符拷贝到联合体中,因为浮点数不能左移运算
&& &for(int i = 0; i & 4; i++)
&& &int hex = 0;
&& &string hexStr = strFloatValue.substr(2 *i, 2);
&& &sscanf(hexStr.c_str(), &%02x&, &hex);
&& &tempUnion.szBuffer[ 3 - i] = // 3-i需要小端模式存放,也就是低字节在低位置
&& &return tempUnion.fV
&& &2.浮点数比较精度/运算精度/转换/溢出/通信问题:
&& &基本所有的浮点数都有精度问题
&& &二进制小数对于十进制小数来说相当于是离散的因此浮点数也只能前面7位可以对上,故有1.0e-07作为浮点数大小区分(实际为6位但是隐藏了1位所以为7位).
&& &1)比较精度问题:浮点数的比较,精度定位到七位或者六位,或者自定义精度,这样可以得到自己想要的结果。
&& &所以浮点数比较需要精度定义:
&& &const double EPSILON = 1.00e-07;
&& &const float&& FLT_EPSILON& = 1.e-07F;
&& &const double& DBL_EPSILON = 2.;
float fValue = 1e-4;
&& &if(fValue &0.00001f && fValue & 0.001f)
&& &&& &int i = 0;
&& &// 二进制转换为浮点数,指数位需要减去127
&& &浮点数也不能表达圆周率pi,所以tan(pi/2)不等于正无穷,也不会溢出。下面的C语言代码
&& &double pi = 3.3832795;
&& &double z = tan(pi/2.0);
&& &的计算结果为95370.0,如果用单精度浮点数,则结果为-。同样的,sin(pi) != 0。
&& &由于浮点数计算过程中丢失了精度,浮点运算的性质与数学运算有所不同。浮点加法和乘法不符合结合律和分配律。
&& &// 科学计数法,e其实是Exponent浮点数指数的意思其实底数是2,1.0是尾数,尾数前面的是符号位
&& &FLT_EPSILON;
&& &float fSValue = 1.0e-07;//等于1.0e-07,1.00e-07,1e-7,等价于1.0 * 10^-7
&& &if(fSValue &0.f && fSValue & 0.000001f) // 其实这里的e-7相当于十进制10^-7的小数的意思
&& &&& &int i = 0; // 将会运行到这里
&& float fValue = -1.0e-7;// -1.0e-7等价于-1.0 * 10 ^-7
&& &if(fValue &-0.000001f && fValue & -0.f)
&& &&& &int i = 0;// 将会运行到这里
&& &简单的浮点数比较:
&& &bool bFloatEqual( float a, float b)
&& &if(fabs(a - b) & FLT_EPSILON)
&& &精确复杂的比较:
&& &bool AlmostEqual2sComplement(float A, float B, int maxUlps) &
&& &// Make sure maxUlps is non-negative and small enough that the &
&& &// default NAN won't compare as equal to anything. &
&& &assert(maxUlps & 0 && maxUlps & 4 * 1024 * 1024); &
&& &int aInt = *(int*)&A; &
&& &// Make aInt lexicographically ordered as a twos-complement int &
&& &if (aInt & 0) &
&& &aInt = 0x - aI &
&& &// Make bInt lexicographically ordered as a twos-complement int &
&& &int bInt = *(int*)&B; &
&& &if (bInt & 0) &
&& &bInt = 0x - bI &
&& &int intDiff = abs(aInt - bInt); &
&& &if (intDiff &= maxUlps) &
&& &2)运算精度问题:浮点数的运算也存在有效位,差异大的数相加减会舍掉小的数的精度,高精度尽量用double表示
&& &float和double的精度是由尾数的位数来决定的。浮点数在内存中是按科学计数法来存储的,其整数部分始终是一个隐含着的“1”,
&& &由于它是不变的,故不能对精度造成影响。
&& &float:2^23 = 8388608,一共七位,这意味着最多能有7位有效数字,但绝对能保证的为6位,也即float的精度为6~7位有效数字;
&& &double:2^52 = 0496,一共16位,同理,double的精度为15~16位。
&& &Visual C++ 2010上的计算结果为0000,而实际的真实值为4322,二进制值为0x4E6B79B2对应,就是0000。
&& &可以看出有效值是6位,如果按四舍五入的话可以精确到8位,其中变量b贡献的有效数值只有2位。
&& &对于这种数量级相差很大的计算,计算结果会保证高位数有效,数量级小的数相对计算结果显的太小了,不能按自身6位的精度保持,而是需要按照计算结果的6位精度保持。
&& &如果你不想你的浮点数在计算上有什么问题,而且你需要精度准确,正确的解决方案不是搞编译参数,
&& &而是——你一定要使用精度更高字节数更多的数据类型,比如:double 或是long double。
&& &3)转换精度问题
&& &直接float,double和 int long long之间转换,因为内存中的表示差异会得到不一样的值,转换会发生错误。
&& &//int num=9; num是整型变量,设为9
  //float* pFloat=&& pFloat表示num的内存地址,但是设为浮点数
&& &//printf(&num的值为:%d\n&,num);& 显示num的整型值
&& &4) 溢出问题
&& &在vc中,可以用float.h中的,用一下函数来判断:
&& &int _isnan(double x) 判断x是不是无效数据(NAN),是返回1,不是返回0
&& &int _finite(double x)判断x是不是无穷大(1.#INF),是返回0,不是返回非零值
&& &int _fpclass(double x)用于检验一个浮点数的类型。
&& &_fpclass的返回值有:
&& &_FPCLASS_SNAN&&&& /* signaling NaN */
&& &//_FPCLASS_QNAN&&&& /* quiet NaN */
&& &//_FPCLASS_NINF&&&& /* negative infinity */
&& &//_FPCLASS_NN&&&&&& /* negative normal */
&& &//_FPCLASS_ND&&&&&& /* negative denormal */
&& &//_FPCLASS_NZ&&&&&& /* -0 */
&& &//_FPCLASS_PZ&&&&&& /* +0 */
&& &//_FPCLASS_PD&&&&&& /* positive denormal */
&& &//_FPCLASS_PN&&&&&& /* positive normal */
&& &//_FPCLASS_PINF&&&& /* positive infinity */
&& &5).通信问题
&& &浮点型在多个处理器间通信时,传递的数值是它的二进制数,比如说这个浮点数的二进制数是0x449A522B
&& &,如果使用串口发送的话,就会发现串口里发送的是0x44、0x9A、0x52和0x2B这4个数
&& &(发送的顺序也可能是逆序,这与约定的字节序有关,与浮点格式无关),
&& &接收端接收到这4个数字后再组合成为00x449A522B,按照IEEE 754的定义被解析成
&& &(从十六进制解析为十进制时候需要解析符号位,指数位减去127,尾数位加上1,转换为float类型的时候会自动转换),这样就实现浮点数通信了。
&& &如果两个处理器所使用的浮点数规则不同,则无法传递浮点数。
&& &想了半天,觉得使用IEEE的浮点数规则来发送是最可靠的,因为任何浮点数都被表示成4个字节,这对发送和接收双方都是个好消息,只要双方都知道要进行浮点数的发送就可以了。而且IEEE格式浮点数的转换是机器内部执行的,我们不再需要任何的转换,不增加运算量,不增加代码量。
&& &按照这个原则,编写了测试代码如下:
&& &发送方A:
&& &float fS //A需要发送的浮点数据
&& &char chSend[4]; //发送缓冲,经过转换后的浮点数据,变成一个字符型数组。
&& &//以下为转换
&& &chSend[0] = *((char *)(&fSend));
&& &chSend[1] = *((char *)(&fSend) + 1);
&& &chSend[2] = *((char *)(&fSend) + 2);
&& &chSend[3] = *((char *)(&fSend) + 3);
&& &此时A就可以将这个数字发送给B了,B接收到的是4个字节表示的一个浮点数,但需要经过如下转换使用:
&& &float fR //接收到的浮点数
&& &char chReceive[4];//接收缓冲。B将接收到的4个字节保存在这里。
&& &//以下为转换
&& &*((char *)(&fReceive)) = chReceive[0];
&& &*((char *)(&fReceive) + 1) = chReceive[1];
&& &*((char *)(&fReceive) + 2) = chReceive[2];
&& &*((char *)(&fReceive) + 3) = chReceive[3];
&& &好了,此时的B已经得到了一个浮点数fR
参考文章:
&& &http://bbs.chinaunix.net/thread--1.html
&& &/zhangziqiu/archive//computercode.html
&& &/icview--1.html
&& &http://blog.csdn.net/quickbasic411/article/details/5921420
&& &/blog/2010/06/ieee_floating-point_representation.html
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:257938次
积分:5022
积分:5022
排名:第3848名
原创:248篇
转载:54篇
译文:10篇
评论:14条
(4)(14)(14)(6)(27)(1)(8)(2)(18)(32)(15)(12)(6)(21)(26)(40)(1)(4)(9)(22)(3)(4)(1)(1)(1)(1)(2)(1)(18)(1)javascript将浮点数转换成整数的三个方法
投稿:whsnow
字体:[ ] 类型:转载 时间:
将浮点数转换成整数方法有很多,本例为大家介绍常用的三个方法,如果读者想到其他好用方法,也可以交流一下
暂时我就想到3个方法而已。如果读者想到其他好用方法,也可以交流一下
Math.floor Math.ceil
Description
一、parseInt
parseInt("13nash");//13
parseInt("")// NaN
parseInt("0xA") //10(十六进制)
parseInt(" 13")//13
parseInt("070")//ES3为56(八进制) ES5为70
parseInt(070)//ES3和ES5都为56
parseInt(22.5)//22
2. 转换规则:
(1). 根据实例(1)得出parseInt会解析一直到非数字时停止
(2). 根据实例(2)得出parseInt解析空字符串时为NaN,而不是0
(3). 根据实例(3)得出parseInt可以将16进制数转换成10进制
(4). 根据实例(4)得出parseInt忽略字符串的空格
(1). 根据实例(5)我们可以知道parseInt在转换八进制数组时是不兼容的。ES3会把070看成八进制数值,但是ES5会将070看成十进制。
(2). 根据实例(6)(7)我们可以知道parseInt在执行的时候会先把参数转变成字符串后再执行变成整数
4. 解释:为什么(5)(6)执行都是执行将070转换成整数,但是结果不一样呢?这个也是解决怎么得到缺点中的第二点。
因为在看官方文档中我看到了If string is not a string, then it is converted to one。这段话。就是说参数如果不是字符串的话,它会先将它转换成字符串再转换成整数。比如实例(6)中parseInt(070),其实是先将070转换成字符串,你可以试下070+""或者String(070)都可以知道070会被转换成"56",因为070是一个八进制。然后就变成了parseInt("56"),最后得出来的整数就是56了。不管你在ES3或者ES5都是为56
二、位操作符
console.log(0 | "123.45")//123
console.log(0 | 123.45)//123
console.log(0 ^ 123.45)//123
console.log(~~123.45)//123
2. 原理:javascript没有整数的概念,所有的数值型都是双精度浮点数。在用位运算符时,它会先把操作数转变成整数,方便操作。而0与其他值异或或者按位或都不会改变操作值的
三、Math.floor与Math.ceil
console.log(Math.floor(2.3)//2
console.log(Math.floor(-2.3)//-3
console.log(Math.ceil(2.3)//3
console.log(Math.ceil(-2.3)//-2
2. 两者不足:Math.floor得到的是数字的最小整数;而Math.ceil得到的是最大整数。所以导致本来-2.3我们取整的话我们要得到的是-2,但是用Math.floor得到的是-3。而2.3用Math.ceil得到的是3,但是我们要的是2就行了。
//自行定义一个函数
function getInt(val){
return val&0 ? Math.floor(val):Math.ceil(val);
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具浮点数转换成整数问题_百度知道各位大神 台达PLC int指令浮点数转换整形数为什么是这样_百度知道&&&&&&&&&&&&&&&&&&
posts - 150,comments - 42,trackbacks - 0
1. 浮点数的表示 与 类型转换http://blog.chinaunix.net/u2/72955/showart_2056507.html&&&&&&float a = 1.0f;&&&&&&cout && (int)a &&&&&&&&cout && (int&)a &&&&&&&&cout && boolalpha && ( (int)a == (int&)a ) && // 输出什么?&&&&float b = 0.0f;&&& cout && (int)b &&&&&&cout && (int&)b &&&&&&cout && boolalpha && ( (int)b == (int&)b ) && // 输出什么?
这个题目涉及float在计算机中的存储问题, IEEE 754的标准就是描述的这个问题。如果这个题目放在笔试的时候应该比面试的时候容易多了。
这个题目的几个答案为1,(0x3f800000H),false,0,0,true。如果你已完美的答出这六个答案,就可以忽略后面的内容。
1.我们先来看一下IEEE 754中关于float,double的存储规范。
无论是单精度还是双精度在存储中都分为三个部分:
1.&符号位(Sign) : 0代表正,1代表为负
2.&指数位(Exponent):用于存储科学计数法中的指数数据,并且采用移位存储
3.&尾数部分(Mantissa):尾数部分
其中float的存储方式如下图所示:
指数部分(E) 占用8-bit的二进制数,可表示数值范围为0-255。 但是指数应可正可负,所以IEEE规定,此处算出的次方须减去127才是真正的指数。所以float的指数可从 -126到128.
尾数部分(M)实际是占用24-bit的一个值,由于其最高位始终为 1 ,所以最高位省去不存储,在存储中只有23-bit。
符号位:s 通过(-1)的s次幂来表示正负号。
而双精度的存储方式为:
我们把E,M从二进制串表示转换为真正的e、m这里要涉及到“规格化(normalized)”、“非规格化(denormalized)”。规格化与否全看指数E!下面分三种情况讨论E,并分别计算e和m:1、规格化:当E的二进制位不全为0,也不全为1时,N为规格化形式。此时e被解释为表示偏置(biased)形式的整数,e值计算公式如下图所示:
上图中,|E|表示E的二进制序列表示的整数值,例如E为"",则|E|=132,e=132-127=5 。 k则表示E的位数,对单精度来说,k=8,则bias=127,对双精度来说,k=11,则bias=1023。
此时m的计算公式如下图所示:
标准规定此时小数点左侧的隐含位为1,那么m=|1.M|。如M="101",则|1.M|=|1.101|=1.625,即 m=1.6252、非规格化:当E的二进制位全部为0时,N为非规格化形式。此时e,m的计算都非常简单。
注意,此时小数点左侧的隐含位为0。&& 为什么e会等于(1-bias)而不是(-bias),这主要是为规格化数值、非规格化数值之间的平滑过渡设计的。后文我们还会继续讨论。有了非规格化形式,我们就可以表示0了。把符号位S值1,其余所有位均置0后,我们得到了 -0.0; 同理,把所有位均置0,则得到 +0.0。非规格化数还有用途,比如表示非常接近0的小数,而且这些小数均匀地接近0,称为“逐渐下溢(gradually underflow)”属性。3、特殊数值:当E的二进制位全为1时为特殊数值。此时,若M的二进制位全为0,则n表示无穷大,若S为1则为负无穷大,若S为0则为正无穷大; 若M的二进制位不全为0时,表示NaN(Not a Number),表示这不是一个合法实数或无穷,或者该数未经初始化。
2.问题的解答
对于1.0f这个数字,我们应该如何表示?按照上面的规则可以得到,符号位为0,指数位为127(0x7F),尾数部分M应该为全0。因此它在计算机中的存储就是0x3F800000H。
cout && (int)a &&
把a从浮点数转换为整数,由于1.0f能够使用32bits完整的表示,没有舍入误差,因此会输出整数 1cout && (int&)a &&
把a里面的内容转换为整数地址,因此编译器会直接浮点数的32位表示直接输出,,即0x3f800000h的10进制表示。
对于0.0f这个特殊的表示上面已经提到了,它在内存中的存储就是全0,因此直接把浮点数转换为整数还是直接把浮点数的表示转化为整数地址结果都是0。
正如上面提到的一样,浮点数-0的表示和+0的表示是不同的,-0在内存中的表示为0xH。
最后再转载一点关于long double的知识,我也没有自己深入。
3.扩展双精度格式(long double)
⑴ 扩展双精度格式(SPARC 结构计算机)
该4倍精度浮点环境符合IEEE关于扩展双精度格式的定义。该浮点环境的4倍精度浮点格式共128位,占4个连续32位字,包含3个构成字段:112位的小数f,15位的偏置指数e,和1位的符号s。将这4个连续的32位字整体作为一个128位的字,进行重新编号。其中0:110位包含小数f;112:126位包含偏置指数e;第127位包含符号位s。如图3所示。
在SPARC结构计算机中,地址最高的32位字存放小数的32位最低有效位,即f[31:0];但是在PowerPC结构计算机中,却是地址最低的32位字存放这些位。
紧邻的两个32位字(在SPARC机中向下计算,在PowerPC机中向上计算)分别存放f[63:32]和f[95:64]。
最后一个字的第0到15位存放小数的最高16位,即f[111:96]。其中第0位存放该16位的最低有效位,第15位存放整个小数f的最高有效位。第16到30位存放15位的偏置指数e,其中第16位存放偏置指数的最低有效位,第30位存放它的最高有效位。最高位,第31位存放符号s。
⑵ 扩展双精度格式(Intel x86结构计算机)
该浮点环境双精度扩展格式符合IEEE双精度扩展格式的定义。该浮点环境的扩展双精度格式共80位,占3个连续32位字,包含四个构成字段:63位的小数f,1位显式前导有效位(explicit leading significand bit)j,15位偏置指数e,和1位符号位s。将这3个连续的32位字整体作为一个96位的字,进行重新编号。其中0:63包含63位的小数f,第63位包含前导有效位j,64:78位包含15位的偏置指数e,最高位第79位包含符号位s。
在Intel结构系计算机中,这些字段依次存放在十个连续的字节中。但是,由于 UNIX& System V Application Binary Interface Intel 386 Processor Supplement (Intel ABI) 要求双精度扩展参数,从而占用堆栈中3个相连地址的32位字,其中最高一个字的高16位未被使用。
&地址最低的32位字存放小数f的低32位,即f[31:0]。其中第0位存放整个小数f的最低有效位LSB 第31位存放小数低32位的最高有效位MSB。
地址居中的32位字,第0到30位存放小数f的31位最高位,即f[62:32]。其中第0位存放31位最高小数位的最低有效位LSB,第30位存放整个小数的最高有效位,地址居中的32位字的最高位第31位存放显式的前导有效位j。&&& 地址最高32位字里,第0到14位存放15位的偏置指数e,第0位存放偏置指数的最低有效位LSB,第14位存放最高有效位MSB,第15位存放符号位s。虽然地址最高的32位字的高16位在Intel x86结构系列机种未被使用,但他们对符合Intel ABI的规定来说,是必需的。=====================================================================================2. 浮点型存储&
先说说32 位的 float型. 一个浮点数 X, 在计算机中表示为:&&&&&&&& X = a& *& 2e&& & 这里 e 代表指数,& a 代表尾数,&& 在 计算机内部, 他们都是用二进制表示的. 其中 a 用二进制的科学表示法表示, 由于科学表示法第一位总是1 (0除外) , 所以第一位略去不计.& e 表示的时候, 因为要表示出负数, 所以 要加上127 ,& 实际运算的时候要减去 127.IEEE 规定, 32 位 float型被拆开成以下格式, 左边为高位 : &&&&&&&&&& 0&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&&& 00&&&&&&& 最高位,第32位&&&&&&&&&&& 第 31-23位,共8位&&&&&&&&&&&&&&& 第23-1位&&&&&&&&&&&& &&&&&&& 符号位&&&&&&&&&&&&&&&&&&&&&&&&&&& 指数位&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 尾数位&&&&& 0为正,1为负&&&&&&&&&&&&&& -127~+127&&&&&&&&&&&&&&&&&&&&&&& 0~0x 7f ff ff
float 的范围是 -3.40282 * e38 ~ + 3.40282 * e38
一般在人看来是 十进制的数, 要转换成二进制. 十进制转二进制, 大于1 的部分就是除以2 取余, 小于1 的部分乘2 取整(上计算机原理课,讲了那么多东西就记得这句话了)&比如 8.5& 转换成二进制就是 1000.1 , 处理成这一步, 还要用科学表示法表示, 就成了 1.0001 * 23 ,& 注意: 由于1.0001 第一个1 要去掉, 所以成了 0001 , 3 需要加上 127 就成了 130 (移码运算,原码加上2^n-1), 二进制就是
套用上面话就表示为:&&&& 0& 00 &&&& 16 进制 就是:&& 0x 41 98 00 00 , 一般来说 , intel 系列的 CPU 都使用的是 小尾存放, 就是 高字节放在后面, 刚好要掉过来就是:&& 0x 00 00 98 41 , 这样就完成了一次浮点数的表示.
注意: 浮点数 0.0& 在计算机中表示为 0x 00 00 00 00 .
那么浮点数的精度是怎么回事情呢? 当我们使用二进制表示 大于1 的部分的时候, 没有问题, 除以2,一直下去, 最后一位肯定不是1 就是 0; 那么小数部分呢?& 举个例子, 比如 0.8 表示&&& 0.8 &&&&&&&&&&&& * 2 &&&&&&&&&&& 1.6 - 1 = 0.6&&&&&&&&&& &&&&&&&&&&&&&&&&&&&&&&&&&&&& * 2 &&&&&&&&&&&&&&&&&&&&&&&&&&&& 1.2 -1 = 0.2& - 0 &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& .* 2&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 0.4 - 0&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *2&&&&& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 0.8 - 0 这样就循环了 就是说 0.8 的二进制 就是& 0. ......& 一直循环下去, 而我们计算机如果表示0.8只能取0后面的前25位(第一个1 略去, ^_^), 这就说明 如果是& 0.01 , 它表示出来的值其实是和 0.8 一样, 所以我们比较float型的数字 用 a == b 其实是没有根据的, 一般都是 用 abs(a - b) & 0..000001应该是hex吧?此处涉及到数学的实数常识,公式|a-b|&c& 转换成& -c&a-b&c)之类就默认是相等.& 所以这就出现了经典的 \精度问题.
那么 double型呢? 咱们可以照 float 型的葫芦 来画了. double 型 只是说 取 64 位, 比float型的位 多一倍, 但是同样 逃不出精度的五指山.& :)IEEE 规定 double 型 , &&& 第64位&&&&&&&&&&&& 63-54&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 53-1 && 符号位&&&&&&&&&&& 指数位 ( -1024 - 1024)&&&&&&&&&&&&&&&&&&& 尾数位
所以 double型的范围是& -1.79769 * e308 ~ +1.79769 * e308多用了几位, 表示范围大了很多, 其实本质跟float型一样.
看来计算机是用来计算的, 一点都不假, 所谓机器智能, 也是人加上去的,& 这就更不用怀疑了.
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/zjumath/archive//4174248.aspx
阅读(...) 评论()

我要回帖

更多关于 浮点数转换 的文章

 

随机推荐