关于float与double结果的误差

 
关于float与double结果的误差2007-09-30 10:41假设有一道题: # _: }# d& k0 f5 w1 r5 m
- F# f9 R8 T) B( c! ^
     float a;
# Z4 z5 V& }2 j; C     a=123456.789e5; 0 r+ G1 e1 @1 \% i, ?* f8 V
     System.out.printf("%f\n",a); # I8 v+ K3 F. ~( y7 n: ]
, u2 j6 y5 B7 H: l% g# a
结果是: ' p5 @$ j- K4 q
9 h+ a' b) v# z" R% J# s+ v; {
    12345678848.000000 6 @9 U8 s5 F& ]$ O1 v( ]
; c* R+ `% x$ C
" g, K+ I  \- u
而不是:   12345678900.000000 & m0 S! v7 v0 x7 \' P- }
- I; B+ F2 ^# |% P% l

# J8 P8 ?9 O7 E8 r% |! @5 a " a3 u/ e" e- f
分析:由于float在内存中占4个字节(32 bit),对于这个数来说会有数据丢失。实型数据是按照指数形式存储的。系统把一个实型数据分成小数部分和整数部分分别存放。在4个字节中,究竟用多少位来表示小数部分,多少位来表示指数部分,对于不同编译器可能会有不同。多数是以3 byte (24 bit) 表示小数部分(包括符号),以1 byte (8 bit) 表示指数部分(包括指数的符号)。 4 q; s2 `/ O$ b" m* h7 i
- {% S  I3 V& r9 C
看看浮点数是怎样炼成的,呵呵: ( M) R$ P$ K" b) Y: {& ]+ w' o

3 T) s# V) _2 V1 \12345678900(十进制)=>
) e) G/ ~/ V! q/ T
% a. n: D- g8 B+ @1011011111110111000001110000110100(34位精确值) 5 X, U' _9 P4 _) a) W

( O$ F& m7 ^& W3 r9 e) G! p, I$ Q========>
# C" P0 w2 Q' U- F$ b; Y0 `! l
4 y/ V: D$ x  I9 k8 c$ G符号位:0
' e* L4 ^% G; F: I' S                           +127
1 k! c% @1 q1 p8 n: U; @指数:33(100001=>00100001 =====> 10100000 5 Z' [: K6 B+ r  g: }1 N
                   原码          阶码(移码)
1 b+ N3 t- i- e* |* I. x5 n& y2 F                  
- x" ~4 }: M+ y7 E: i尾数:1.01101111111011100000111(取24位)
5 P: @' C( @2 z- Z' ?( K1 A , J4 N4 j) y% b1 u9 O0 r
=>(注意:前面的1在实际存放时为了多存放一位而隐含,即浮点数的尾数的最高位永远隐含为1)
1 `, p/ a" `; `0 10100000 01101111111011100000111(实际放了尾数后面的23位)
; b8 X; P  H2 K3 D0 " [  a     指数           尾数 0 S- O, w  o' E; \
   
7 Y6 X7 X$ J4 S1 o) L7 a( h最后结果就是01010000001101111111011100000111
# ]- a: h2 o" s9 `/ A 1 x" E1 }; _5 C
现在再把它还原成整数:
/ Y. g. @; Q7 x& J+ w/ v  P' C(1)取尾数23位:01101111111011100000111 : v% l& y, H* |& N; M, X) `- z
(2)在前面加上隐含的1,变成:101101111111011100000111
+ H: X: K, M' M/ i3 [: ^(3)取指数8位:10100000 2 [- ~6 G$ K0 i" C) p; b6 ]- }8 W
(4)指数减127得:100001(33)
! F- Z- m' A6 V# p6 ^(5)尾数向左移动10位(尾数本身23位,33-23=10):1011011111110111000001110000000000
6 g. i' s! K; g' b4 r此即12345678848 + H: V/ `) [' {! y* v
( c$ y) [: J3 Y$ a
) G3 q, d/ Z! b& _9 L& J' d" S! l' S

6 B* v$ Y. [7 N9 d; @启示:在需要精确答案的地方,要避免使用float和double;对于货币计算,要使用int、long(把零钱换成分来表示,这时就没有小数位,然后结果再除以相应的权值.)或BigDecimal。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: floatdouble都是浮点数类型,用于存储小数。float通常用于占用空间较小的场景,例如移动设备或嵌入式系统。double则通常用于需要更高精度的场景,例如科学计算或金融计算。在编程中,需要根据具体情况选择使用哪种类型。 ### 回答2: floatdouble都是用来表示浮点数的数据类型。它们的主要区别在于精度和内存占用。 首先,当我们需要更高的精度时,应该使用doubledouble类型的变量可以提供更高的精确度,通常使用64位来存储浮点数,因此能够表示更大的值范围和更小的小数位。例如,如果需要进行一些复杂的科学计算或者需要更加精确的结果,double类型是更好的选择。 其次,当我们对内存占用有限制时,可以考虑使用floatfloat类型使用32位存储浮点数,因此它占用的内存空间比double类型更小。如果我们处理的数据量很大,需要存储大量的浮点数,那么使用float类型可以节省内存空间。 另外,也要考虑到程序的目标和需求。如果我们的应用程序对精度没有特别高的要求,并且内存占用也不是主要问题,那么可以选择使用double类型。因为双精度浮点数在大多数情况下提供了足够的精度和范围,而且现代计算机处理速度越来越快,性能差异可能不太明显。 总之,选择使用float还是double,应该根据实际需求来决定。如果需要更高的精度,或者对内存占用有限制,可以使用doublefloat,否则,可能更倾向于使用double类型。 ### 回答3: floatdouble都是C语言中的浮点数据类型,用于存储小数。 float是单精度浮点数,占用4个字节,能够存储的有效位数为6~7位。它通常用于对内存占用要求比较高、精度要求不高的场景。例如,使用float可以存储一些简单的测量值,如温度、速度等。 double是双精度浮点数,占用8个字节,能够存储的有效位数为15~16位。它精度更高,通常用于对精度要求较高的场景。例如,使用double可以存储一些需要高精度计算的数据,如金融数据、科学计算等。 在选择使用float还是double时,需要根据具体的需求来决定。如果对精度要求比较高,或者需要进行大量的浮点数运算,那么应该选择double。如果只是存储一些简单的测量值或者内存占用要求比较高,可以选择float。需要注意的是,使用floatdouble时都要注意浮点数的精度问题,尽量避免在比较浮点数时直接使用"=="来判断相等性,而是应该使用一个允许误差的判断方式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值