打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
精确计算java中float和double的精度

[本文相关的代码放在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  


本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
java四类八种基本数据类型
JAVA中float与double的区别
Java基础学习的八大基本变量
JAVA中控制double和float的精度
java,c,c语言之间基本数据类型的比较
java基本数据类型
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服