当前位置: 首页 > news >正文

关于float与double结果的误差

原文: http://bbs.51cto.com/thread-542195-1.html
关于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。

相关文章:

  • 如何将int整型、float类型(或double)转换成字符串(或CString)_liangchaoxi的IT博客_新浪博客......
  • 如何将int整型、float类型(或double)转换成字符串(或CString)
  • C语言 低通滤波器\带通滤波器\高通滤波器_liangchaoxi的IT博客_新浪博客
  • C语言 低通滤波器\带通滤波器\高通滤波器
  • 如何学习matlab
  • 如何学习matlab_liangchaoxi的IT博客_新浪博客
  • 奈奎斯特抽样定理_liangchaoxi的IT博客_新浪博客
  • 奈奎斯特抽样定理
  • 数值转换成字符串 字符字符串转换成数值_liangchaoxi的IT博客_新浪博客
  • 数值转换成字符串 字符字符串转换成数值
  • 一个字母、数字、汉字所占用的内存空间_liangchaoxi的IT博客_新浪博客
  • 一个字母、数字、汉字所占用的内存空间
  • 【CRC算法】CRC算法、原理及程序_liangchaoxi的IT博客_新浪博客
  • 【CRC算法】CRC算法、原理及程序
  • n%2==1什么意思?n/2什么意思?有n\2这种写法吗?_liangchaoxi的IT博客_新浪博客
  • 07.Android之多媒体问题
  • 10个最佳ES6特性 ES7与ES8的特性
  • 2017 年终总结 —— 在路上
  • avalon2.2的VM生成过程
  • CentOS 7 修改主机名
  • miniui datagrid 的客户端分页解决方案 - CS结合
  • swift基础之_对象 实例方法 对象方法。
  • 从伪并行的 Python 多线程说起
  • 浮现式设计
  • 缓存与缓冲
  • 看域名解析域名安全对SEO的影响
  • 马上搞懂 GeoJSON
  • 爬虫模拟登陆 SegmentFault
  • 配置 PM2 实现代码自动发布
  • ​二进制运算符:(与运算)、|(或运算)、~(取反运算)、^(异或运算)、位移运算符​
  • ​虚拟化系列介绍(十)
  • ${ }的特别功能
  • $forceUpdate()函数
  • (+3)1.3敏捷宣言与敏捷过程的特点
  • (二) Windows 下 Sublime Text 3 安装离线插件 Anaconda
  • (力扣题库)跳跃游戏II(c++)
  • (免费领源码)Java#Springboot#mysql农产品销售管理系统47627-计算机毕业设计项目选题推荐
  • (牛客腾讯思维编程题)编码编码分组打印下标题目分析
  • (五)网络优化与超参数选择--九五小庞
  • (轉貼) 蒼井そら挑戰筋肉擂台 (Misc)
  • .“空心村”成因分析及解决对策122344
  • .NET 4.0网络开发入门之旅-- 我在“网” 中央(下)
  • .net framework profiles /.net framework 配置
  • .NET8.0 AOT 经验分享 FreeSql/FreeRedis/FreeScheduler 均已通过测试
  • .net下的富文本编辑器FCKeditor的配置方法
  • @EnableConfigurationProperties注解使用
  • [ CTF ]【天格】战队WriteUp- 2022年第三届“网鼎杯”网络安全大赛(青龙组)
  • [ 代码审计篇 ] 代码审计案例详解(一) SQL注入代码审计案例
  • [ 云计算 | AWS ] 对比分析:Amazon SNS 与 SQS 消息服务的异同与选择
  • [2016.7 Day.4] T1 游戏 [正解:二分图 偏解:奇葩贪心+模拟?(不知如何称呼不过居然比std还快)]
  • [AIGC] SQL中的数据添加和操作:数据类型介绍
  • [BeginCTF]真龙之力
  • [C# WPF] DataGrid选中行或选中单元格的背景和字体颜色修改
  • [C#]使用PaddleInference图片旋转四种角度检测
  • [C++]C++入门--引用