C语言中 Float的精度 比较 加减算法问题

逆霜 2014-03-12 07:35:55
首先,Float的存储方式我明白,这个不用讲了。
问题1:Float根据符号位,指数为,有效位转换成功后,存储在内存中的时候是直接存储的转换后的字符,还是将转换后的字符取补码存储?
问题2:Float在存储的时候指数要用到指数偏差,是为了解决"如果使用二补数的有号数,会产生不易比较"的问题,我想知道Float是如何实现比较的。
问题3:Float有精度缺失,譬如2.25存储时是不会的,但是2.2存储的时候应为0.2无法取准,会产生精度缺失,这个我明白算法。然后另一种譬如我的值是1.23456789,有效位是9位,溢出了2位,这个在存储的时候是怎么处理的,直接丢失吗?
问题4:Float的加减法,int等整型的加减法是通过补码运算的,那Float的运算是怎么进行的?

thanks各位大神!
...全文
1322 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
lm_whales 2015-07-26
  • 打赏
  • 举报
回复
引用 12 楼 jinianjun 的回复:
[quote=引用 9 楼 lm_whales 的回复:] 尾数减法,对齐后,直接相减(或者相加,看符号位,并且连隐含位一起计算), 然后确定结果的符号, 然后根据结果的0的个数,调整结果的指数位数,以及尾数。 浮点运算,通过硬件实现的时候,也可能中间转换为补码表示(即正数用原码,负数用补码表示) 计算出结果,再调整指数,符号,尾数的位数,以及各种标志位
直接相减不对吧。比如2-(-3)=2+3=5;如果二进制直接减的话,数值部分,2-3=0000 0010-0000 0011=-1,符号位暂且不论怎么处理,数值部分肯定不对了。[/quote] 直接减没问题,反正要处理符号问题。 例如 2-3 =10 -11 = 11 =-1; 需要借位,结果为负数 (1)0-1 =1,(1)0-1=1 ; 结果为11 负数取下绝对值为1, 然后修正一下符号位。 比如 2,3 都是正数 符号位为0 此时因该设为1 这样 尾数m=1.符号位 s=1 这对于计算机硬件很简单, 就是你自己计算,也不过把负数结果的当作补码数。 然后处理符号的时候,恢复成原码数。 原码正数,其实就相当于无符号数 要知道,有符号数,无符号数加减法, 对于计算机来说 ,没有任何区别。 有区别的,只是结果的意义,有无溢出。
jinianjun 2015-07-25
  • 打赏
  • 举报
回复
引用 9 楼 lm_whales 的回复:
尾数减法,对齐后,直接相减(或者相加,看符号位,并且连隐含位一起计算), 然后确定结果的符号, 然后根据结果的0的个数,调整结果的指数位数,以及尾数。 浮点运算,通过硬件实现的时候,也可能中间转换为补码表示(即正数用原码,负数用补码表示) 计算出结果,再调整指数,符号,尾数的位数,以及各种标志位
直接相减不对吧。比如2-(-3)=2+3=5;如果二进制直接减的话,数值部分,2-3=0000 0010-0000 0011=-1,符号位暂且不论怎么处理,数值部分肯定不对了。
lm_whales 2015-07-25
  • 打赏
  • 举报
回复
另外,十进制转换成浮点数,会有精度损失,而输入输出函数,都是有精度的(按照十进制处理) 输入输出的数据(内存中为浮点数二进制表示),和字符串表示的十进制浮点数,通常会有出入
lm_whales 2015-07-25
  • 打赏
  • 举报
回复
浮点数有规则化浮点数和非规则化浮点数 非规则化浮点数,隐含位为0,都是绝对值非常小的数 ,比 1 E-xxx 小(xxx是负的指数的绝对值的最大值), 此时指数为定值,尾数前面若干位可以是0 规则化浮点数,隐含位为1,相对来书比较大, 尾数第一位固定为1,也就是隐含位为1, 当指数相差很大时,较小的数有可能经过对齐后为零 不过,X86内部浮点寄存器,是80 位(或者更多位),而通常的 float,double 分别是32,64 位 经过扩展后,变成80 位浮点数(或者更多位), 再计算的,所以如果你自己模拟的话,可能和计算机计算的结果,有所不同。
lm_whales 2015-07-25
  • 打赏
  • 举报
回复
尾数减法,对齐后,直接相减(或者相加,看符号位,并且连隐含位一起计算), 然后确定结果的符号, 然后根据结果的0的个数,调整结果的指数位数,以及尾数。 浮点运算,通过硬件实现的时候,也可能中间转换为补码表示(即正数用原码,负数用补码表示) 计算出结果,再调整指数,符号,尾数的位数,以及各种标志位
jinianjun 2015-07-25
  • 打赏
  • 举报
回复
引用 7 楼 lm_whales 的回复:
浮点数的尾数,是原码表示的,不是补码表示 指数部分是移码表示的 加减的时候和手动加减一样,先看符号,再对齐指数,再尾数加减。 浮点数的设计,主要方便乘除计算,而不是加减计算。 数据丢失看硬件设计,或者软件实现。可能有舍入圆整,也可能没有舍入圆整(直接舍去) 这可能是硬件设计的时候就固定下来的,也可能是设计为,可以控制的和选择的。 至于软件实现,很多浮点库,是为了仿真对应的硬件实现,这种软件实现可能和硬件实现一致。 比如,TC,可以使用硬件浮点库计算,也可以软件仿真计算浮点数运算 这种软件实现,就是软件实现FPU的指令代码,每条指令,都有对应的软件代码实现他。 当浮点处理器,不存在的时候,可以用软件仿真指令,直接代替对应的硬件指令。 也有可能只是实现一个浮点运算库,那么就是库的设计者的事情了。
这位说的还是很切题的。但是提主还有个问题没有答出来,同时也是我的疑问。“浮点数的尾数,是原码表示的,不是补码表示”,那么减法的时候,尾数是如何相减的。
lm_whales 2014-03-20
  • 打赏
  • 举报
回复
浮点数的尾数,是原码表示的,不是补码表示 指数部分是移码表示的 加减的时候和手动加减一样,先看符号,再对齐指数,再尾数加减。 浮点数的设计,主要方便乘除计算,而不是加减计算。 数据丢失看硬件设计,或者软件实现。可能有舍入圆整,也可能没有舍入圆整(直接舍去) 这可能是硬件设计的时候就固定下来的,也可能是设计为,可以控制的和选择的。 至于软件实现,很多浮点库,是为了仿真对应的硬件实现,这种软件实现可能和硬件实现一致。 比如,TC,可以使用硬件浮点库计算,也可以软件仿真计算浮点数运算 这种软件实现,就是软件实现FPU的指令代码,每条指令,都有对应的软件代码实现他。 当浮点处理器,不存在的时候,可以用软件仿真指令,直接代替对应的硬件指令。 也有可能只是实现一个浮点运算库,那么就是库的设计者的事情了。
merlinfang 2014-03-13
  • 打赏
  • 举报
回复
1、尾数位和整数一样的方式,负数也是补码的 2、靠浮点CPU实现的,一般也不清楚 3、直接丢了 4、靠浮点CPU实现的
merlinfang 2014-03-13
  • 打赏
  • 举报
回复
引用 4 楼 changlishuang 的回复:
[quote=引用 1 楼 merlinfang 的回复:] 1、尾数位和整数一样的方式,负数也是补码的 2、靠浮点CPU实现的,一般也不清楚 3、直接丢了 4、靠浮点CPU实现的
对于3、直接丢了,为什么我在Turbo C里面 float a = 12345678 ; printf("%f",a); 输出的a还是有8位,不是应该有丢失么[/quote] 你这个例子不对的,12345678 转成二进制是101111000110000101001110 是24位, 除了固定的1只要23位就能存储了, 而浮点数正好能存23位,所以没有丢失
逆霜 2014-03-13
  • 打赏
  • 举报
回复
引用 1 楼 merlinfang 的回复:
1、尾数位和整数一样的方式,负数也是补码的 2、靠浮点CPU实现的,一般也不清楚 3、直接丢了 4、靠浮点CPU实现的
对于3、直接丢了,为什么我在Turbo C里面 float a = 12345678 ; printf("%f",a); 输出的a还是有8位,不是应该有丢失么
赵4老师 2014-03-13
  • 打赏
  • 举报
回复
mangoalx 2014-03-13
  • 打赏
  • 举报
回复
问题3:Float有精度缺失,譬如2.25存储时是不会的,但是2.2存储的时候应为0.2无法取准,会产生精度缺失,这个我明白算法。 这个我不明白,能解释下不,为啥2.2就已经不准了?
逆霜 2014-03-13
  • 打赏
  • 举报
回复
引用 5 楼 merlinfang 的回复:
[quote=引用 4 楼 changlishuang 的回复:]
[quote=引用 1 楼 merlinfang 的回复:]
1、尾数位和整数一样的方式,负数也是补码的
2、靠浮点CPU实现的,一般也不清楚
3、直接丢了
4、靠浮点CPU实现的


对于3、直接丢了,为什么我在Turbo C里面 float a = 12345678 ; printf("%f",a); 输出的a还是有8位,不是应该有丢失么[/quote]

你这个例子不对的,12345678 转成二进制是101111000110000101001110 是24位, 除了固定的1只要23位就能存储了, 而浮点数正好能存23位,所以没有丢失[/quote]

哦,明白了,虽然说精度只有7,但是并不是一定我的数超过7位就会溢出,要转换为浮点数的存储方式后在看是否超过23位,这里的7位只是大概值,而每个数是否溢出还要看特殊情况,譬如22345678 为 1010101001111011111001110,虽然第一个1到最后有25位,但是最后的0可以舍弃然后进阶,而第一位也可以按浮点数算法忽略,还是23位,但是22345678就会溢出,因为最后一位为1了。
然后还有一个问题这个我不理解怎么算出来的。求解。

3,882

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 其它技术问题
社区管理员
  • 其它技术问题社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧