[本文相关的代码放在github上。地址为:https://github.com/VigourJiang/StructuredFloat]

Java中double类型的格式基本遵循IEEE 754标准。

虽然数学意义上的小数是连续的。但double只能表示当中的一些离散点。把这些离散点组成的集合记为S。S的大小还是有限的。假设要保存的小数P刚好在集合S内,那么double类型就能精确的表示P;否则double类型只能从集合S中找一个与P近期的离散点P'取代P。

以上表述对于float也成立。IEEE 754中float和double的表示策略全然同样。差别只体如今各个字段(指数字段、小数字段)的bit数量不同。

也就是说。float和double都是不精确的,因此偶尔会有一些奇怪的事情发生:

  1. double d = 1e16d;
  2.  
  3. double d2 = d +1.0d - d;
  4.  
  5. // 下面代码输出0.0,而不是1.0
  6. System.out.println(d2);

上述结果或许并不有趣。由于在学C语言的时候。你的老师就可能提醒过你。但有趣的是,float和double到底有多不精确?给定一个double d = XXX,与d最接近的另外两个double的数值是多少?

我用Java写了一个解析原始数据类型float和double的类StructuredFloat,给定一个float或者double数值P。它能够计算出与P的绝对值近期的、能够被float/double表示的浮点数。以下是使用方法:

  1. double cur = 3.23d; // any valid double value
  2. StructuredFloat sd = com.vigour.StructuredFloat.StructedFloatBuilder.buildDouble(cur);
  3. StructuredFloat smaller = sd.absSmaller();
  4. StructuredFloat bigger = sd.absBigger();
  5.  
  6. if(smaller != null){
  7. double smaller_double = smaller.getBigDecimal().doubleValue();
  8. // now you get the nearest double value whose absolute value is smaller
  9. }
  10. if(bigger!= null){
  11. double bigger_double = bigger.getBigDecimal().doubleValue();
  12. // now you get the nearest double value whose absolute value is bigger
  13. }

以下是一些有趣的输出,能够看到,在1e16d附近double的精度就小于1了,在1e7f(一千万)附近。float的精度就等于1了,float果然难堪大用。

  1. -------------Some Interesting Resule for Double--------------------
  2. // 0.1d附近的double
  3. Nearest smaller double: 0.09999999999999999167332731531132594682276248931884765625
  4. Current double: 0.1000000000000000055511151231257827021181583404541015625
  5. Nearest bigger double : 0.10000000000000001942890293094023945741355419158935546875
  6.  
  7. // 1.0d附近的double
  8. Nearest smaller double: 0.99999999999999988897769753748434595763683319091796875
  9. Current double: 1
  10. Nearest bigger double : 1.0000000000000002220446049250313080847263336181640625
  11.  
  12. // 10.0d附近的double
  13. Nearest smaller double: 9.9999999999999982236431605997495353221893310546875000
  14. Current double: 10.00
  15. Nearest bigger double : 10.0000000000000017763568394002504646778106689453125000
  16.  
  17. // 1e14d附近的double
  18. Nearest smaller double: 99999999999999.9843750000000000000000000000000000000000000000000000
  19. Current double: 100000000000000.00000000000000000000000000000000
  20. Nearest bigger double : 100000000000000.0156250000000000000000000000000000000000000000000000
  21.  
  22. // 1e15d附近的double
  23. Nearest smaller double: 999999999999999.8750000000000000000000000000000000000000000000000000
  24. Current double: 1000000000000000.0000000000000000000000000000000000
  25. Nearest bigger double : 1000000000000000.1250000000000000000000000000000000000000000000000000
  26.  
  27. // 1e16d附近的double
  28. Nearest smaller double: 9999999999999998.0000000000000000000000000000000000000000000000000000
  29. Current double: 10000000000000000.0000000000000000000000000000000000000
  30. Nearest bigger double : 10000000000000002.0000000000000000000000000000000000000000000000000000
  31.  
  32. // 1e17d附近的double
  33. Nearest smaller double: 99999999999999984.0000000000000000000000000000000000000000000000000000
  34. Current double: 100000000000000000.000000000000000000000000000000000000000
  35. Nearest bigger double : 100000000000000016.0000000000000000000000000000000000000000000000000000
  36.  
  37. // 1e304d附近的double
  38. Nearest smaller double: 9999999999999998174371273630364736815867488735718786093662414371947263704524926751224722911637244940234972882804879769415602664816552507597839565690480126952738889402600333599657997758603312171995012866291845554976690497648524473448849371595248581587050582985041870802940253992811266476846330599148879872.0000000000000000000000000000000000000000000000000000
  39. Current double: 9999999999999999392535525055364621860040287220117324953190771571323204563013233902843309257440507748436856118056162172578717193742636030530235798840866882774987301441682011041067710253162440905843719802548551599076639682550821832659549112269607949805346034918662572406407604380845959862074904348138143744.000000000000000000000000000000000000000000000000
  40. Nearest bigger double : 10000000000000000610699776480364506904213085704515863812719128770699145421501541054461895603243770556638739353307444575741831722668719553462632031991253638597235713480763688482477422747721569639692426738805257643176588867453119191870248852943967318023641486852283274009874954768880653247303478097127407616.0000000000000000000000000000000000000000000000000000
  41.  
  42. -------------Some Interesting Resule for Float--------------------
  43.  
  44. // 0.1f附近的float
  45. Nearest smaller float: 0.0999999940395355224609375
  46. Current float: 0.100000001490116119384765625
  47. Nearest bigger float: 0.10000000894069671630859375
  48.  
  49. // 1.0f附近的float
  50. Nearest smaller float: 0.999999940395355224609375
  51. Current float: 1
  52. Nearest bigger float: 1.00000011920928955078125
  53.  
  54. // 10.0f附近的float
  55. Nearest smaller float: 9.99999904632568359375000
  56. Current float: 10.00
  57. Nearest bigger float: 10.00000095367431640625000
  58.  
  59. // 1e5f附近的float
  60. Nearest smaller float: 99999.99218750000000000000000
  61. Current float: 100000.00000000000
  62. Nearest bigger float: 100000.00781250000000000000000
  63.  
  64. // 1e6f附近的float
  65. Nearest smaller float: 999999.93750000000000000000000
  66. Current float: 1000000.0000000000000
  67. Nearest bigger float: 1000000.06250000000000000000000
  68.  
  69. // 1e7f附近的float
  70. Nearest smaller float: 9999999.00000000000000000000000
  71. Current float: 10000000.0000000000000000
  72. Nearest bigger float: 10000001.00000000000000000000000
  73.  
  74. // 1e8f附近的float
  75. Nearest smaller float: 99999992.00000000000000000000000
  76. Current float: 100000000.000000000000000000
  77. Nearest bigger float: 100000008.00000000000000000000000
  78.  
  79. // 1e38f附近的float
  80. Nearest smaller float: 99999986661652122824821048795547566080.00000000000000000000
  81. Current float: 99999996802856924650656260769173209088.00000000000000000000000
  82. Nearest bigger float: 100000006944061726476491472742798852096.0000000000000000000000

精确计算java中float和double的精度的更多相关文章

  1. Java中 float、double使用注意问题

    在java中运行一下代码 System.out.println(2.00-1.10);输出的结果是:0.8999999999999999很奇怪,并不是我们想要的值0.9 再运行如下代码:System. ...

  2. Java中float和double转换的问题

    为什么double转float不会出现数据误差,而float转double却误差如此之大?   double d = 3.14; float f = (float)d; System.out.prin ...

  3. Java中float、double、long类型变量赋值添加f、d、L尾缀问题

    展开1. 添加尾缀说明 我们知道Java在变量赋值的时候,其中float.double.long数据类型变量,需要在赋值直接量后面分别添加f或F.d或D.l或L尾缀来说明.  其中,long类型最好以 ...

  4. JAVA中float与double的区别

    float是单精度类型,精度是8位有效数字,取值范围是10的-38次方到10的38次方,float占用4个字节的存储空间 double是双精度类型,精度是17位有效数字,取值范围是10的-308次方到 ...

  5. java中float和double的区别

    float表示单精度浮点数在机内占4个字节,用32位二进制描述. double表示双精度浮点数在机内占8个字节,用64位二进制描述.浮点数在机内用指数型式表示,分解为:数符,尾数,指数符,指数四部分. ...

  6. 【转】JAVA程序中Float和Double精度丢失问题

    原文网址:http://blog.sina.com.cn/s/blog_827d041701017ctm.html 问题提出:12.0f-11.9f=0.10000038,"减不尽" ...

  7. Java中float/double取值范围与精度

    Java浮点数 浮点数结构 要说清楚Java浮点数的取值范围与其精度,必须先了解浮点数的表示方法,浮点数的结构组成,之所以会有这种所谓的结构,是因为机器只认识01,你想表示小数,你要机器认识小数点这个 ...

  8. 【转载】 C#中float、double以及decimal类型有何不同

    在C#语言中,float.double以及decimal类型都可以用来表示小数,但三者还是有一定的不同,有效数字为相比的话,decimal类型的有效数字最大,float类型最小.计算浮点类型的运算,如 ...

  9. Java中long和double的原子性

    Java中long和double的原子性 java中基本类型中,long和double的长度都是8个字节,32位(4字节)处理器对其读写操作无法一次完成,那么,JVM,long和double是原子性的 ...

随机推荐

  1. Errors reported here must be corrected before the service can be started

    场景: 安装.配置Apache24时候,最后会给出提示,如图:Errors reported here must be corrected before the service can be star ...

  2. select count(1) 和 select count(*)的区别

    统计一个表T有多少行数据,通常写法是: 查询A:select count(*) from T 但也可以采用下面语句来查: 查询B:select count(1) from T 结果通常是一样的.那么二 ...

  3. MERGE INTO USING用法

    MERGE INTO [your table-name] [rename your table here] USING ( [write your query here] )[rename your ...

  4. CodeFrist基础_迁移更新数据

    一丶自动迁移 第一次启用迁移:NeGet-->Enable-Migrations public DemoDbContext() : base("name=ConncodeFirst&q ...

  5. 【LeetCode】7、Reverse Integer(整数反转)

    题目等级:Easy 题目描述: Given a 32-bit signed integer, reverse digits of an integer. Example 1: Input: 123 O ...

  6. vivo手机执行input命令提示killed

    异常现象: 使用vivo手机时发现通过inputManager发送按键.执行屏幕滑动等动作失效,相关API并没有任何异常抛出,继续跟踪发现shell控制台执行input进行屏幕滑动.发送文本.模拟按键 ...

  7. 我的MYSQL学习心得链接

    http://www.cnblogs.com/lyhabc/p/3793524.html

  8. cookie domain path 跨域

    1.domain表示的是cookie所在的域,默认为请求的地址,如网址为www.jb51.net/test/test.aspx,那么domain默认为www.jb51.net.而跨域访问,如域A为t1 ...

  9. 【汇总】java中数组的声明、初始化及遍历

    java中数组用来存储固定大小的同类型元素 一维数组: 1.数组的声明: //声明一维数组,推荐用第一种 int[] a; int b[]; 2.数据的初始化:有三种初始化方式 (1).静态初始化 / ...

  10. 关于ISIS协议 CSNP报文的周期更新理解

    为何ISIS协议的CSNP报文在MA网络环境中是以周期更新然而在P2P网络环境中只更新一次? 个人通过视频及资料学习理解: 我们知道ISIS的CSNP报文类似OSPF中的DBD报文,作用就是用来确认彼 ...