java float和double的精度_精确计算java中float和double的精度

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

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

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

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

double d = 1e16d;

double d2 = d +1.0d - d;

// 下面代码输出0.0,而不是1.0

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

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

double cur = 3.23d; // any valid double value

StructuredFloat sd = com.vigour.StructuredFloat.StructedFloatBuilder.buildDouble(cur);

StructuredFloat smaller = sd.absSmaller();

StructuredFloat bigger = sd.absBigger();

if(smaller != null){

double smaller_double = smaller.getBigDecimal().doubleValue();

// now you get the nearest double value whose absolute value is smaller

}

if(bigger!= null){

double bigger_double = bigger.getBigDecimal().doubleValue();

// now you get the nearest double value whose absolute value is bigger

}

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

-------------Some Interesting Resule for Double--------------------

// 0.1d附近的double

Nearest smaller double: 0.09999999999999999167332731531132594682276248931884765625

Current double: 0.1000000000000000055511151231257827021181583404541015625

Nearest bigger double : 0.10000000000000001942890293094023945741355419158935546875

// 1.0d附近的double

Nearest smaller double: 0.99999999999999988897769753748434595763683319091796875

Current double: 1

Nearest bigger double : 1.0000000000000002220446049250313080847263336181640625

// 10.0d附近的double

Nearest smaller double: 9.9999999999999982236431605997495353221893310546875000

Current double: 10.00

Nearest bigger double : 10.0000000000000017763568394002504646778106689453125000

// 1e14d附近的double

Nearest smaller double: 99999999999999.9843750000000000000000000000000000000000000000000000

Current double: 100000000000000.00000000000000000000000000000000

Nearest bigger double : 100000000000000.0156250000000000000000000000000000000000000000000000

// 1e15d附近的double

Nearest smaller double: 999999999999999.8750000000000000000000000000000000000000000000000000

Current double: 1000000000000000.0000000000000000000000000000000000

Nearest bigger double : 1000000000000000.1250000000000000000000000000000000000000000000000000

// 1e16d附近的double

Nearest smaller double: 9999999999999998.0000000000000000000000000000000000000000000000000000

Current double: 10000000000000000.0000000000000000000000000000000000000

Nearest bigger double : 10000000000000002.0000000000000000000000000000000000000000000000000000

// 1e17d附近的double

Nearest smaller double: 99999999999999984.0000000000000000000000000000000000000000000000000000

Current double: 100000000000000000.000000000000000000000000000000000000000

Nearest bigger double : 100000000000000016.0000000000000000000000000000000000000000000000000000

// 1e304d附近的double

Nearest smaller double: 9999999999999998174371273630364736815867488735718786093662414371947263704524926751224722911637244940234972882804879769415602664816552507597839565690480126952738889402600333599657997758603312171995012866291845554976690497648524473448849371595248581587050582985041870802940253992811266476846330599148879872.0000000000000000000000000000000000000000000000000000

Current double: 9999999999999999392535525055364621860040287220117324953190771571323204563013233902843309257440507748436856118056162172578717193742636030530235798840866882774987301441682011041067710253162440905843719802548551599076639682550821832659549112269607949805346034918662572406407604380845959862074904348138143744.000000000000000000000000000000000000000000000000

Nearest bigger double : 10000000000000000610699776480364506904213085704515863812719128770699145421501541054461895603243770556638739353307444575741831722668719553462632031991253638597235713480763688482477422747721569639692426738805257643176588867453119191870248852943967318023641486852283274009874954768880653247303478097127407616.0000000000000000000000000000000000000000000000000000

-------------Some Interesting Resule for Float--------------------

// 0.1f附近的float

Nearest smaller float: 0.0999999940395355224609375

Current float: 0.100000001490116119384765625

Nearest bigger float: 0.10000000894069671630859375

// 1.0f附近的float

Nearest smaller float: 0.999999940395355224609375

Current float: 1

Nearest bigger float: 1.00000011920928955078125

// 10.0f附近的float

Nearest smaller float: 9.99999904632568359375000

Current float: 10.00

Nearest bigger float: 10.00000095367431640625000

// 1e5f附近的float

Nearest smaller float: 99999.99218750000000000000000

Current float: 100000.00000000000

Nearest bigger float: 100000.00781250000000000000000

// 1e6f附近的float

Nearest smaller float: 999999.93750000000000000000000

Current float: 1000000.0000000000000

Nearest bigger float: 1000000.06250000000000000000000

// 1e7f附近的float

Nearest smaller float: 9999999.00000000000000000000000

Current float: 10000000.0000000000000000

Nearest bigger float: 10000001.00000000000000000000000

// 1e8f附近的float

Nearest smaller float: 99999992.00000000000000000000000

Current float: 100000000.000000000000000000

Nearest bigger float: 100000008.00000000000000000000000

// 1e38f附近的float

Nearest smaller float: 99999986661652122824821048795547566080.00000000000000000000

Current float: 99999996802856924650656260769173209088.00000000000000000000000

Nearest bigger float: 100000006944061726476491472742798852096.0000000000000000000000

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值