binary_double in oracle中的binary_double,double in Java使用IEEE 754标准。
但是它们的准确性有所不同。
例如,值:
456.67d
oracle:
declare
a BINARY_DOUBLE := 456.67d;
begin
SYS.DBMS_OUTPUT.PUT_Line(TO_CHAR(a,'9.99999999999999999999EEEE'));
end;
结果:4.56670000000000020000E 02
java:
Double d = 456.67d;
DecimalFormat formatter = new DecimalFormat("0.000000000000000000000E000");
System.out.println(formatter.format(d));
结果:4.566700000000000000000E002
Java中的值不及Oracle中的准确。
在线转换器说,456.67D的最准确表示是:
4.56670000000000015916157281026E2
那么,为什么在Java的精度中与Oracle中的精度不同?以及如何获得Java更准确的价值?
使用bigdecimal:
Double d = 456.67d;
BigDecimal bd = new BigDecimal( d );
bd.setScale( 50 );
System.out.println( bd );
DecimalFormat formatter = new DecimalFormat("0.000000000000000000000E000");
System.out.println( formatter.format( bd ) );
输出:
456.67000000000001591615728102624416351318359375
4.566700000000000159162E002
两者都是准确的。他们只是使用不同的策略来打印。
这是通过Squeak Smalltalk打印的确切值(但是语言无关紧要,这是相同的表示且算术相同的(:
d := 456.67.
{
d predecessor asFraction printShowingMaxDecimalPlaces: 50.
d asFraction printShowingMaxDecimalPlaces: 50.
d successor asFraction printShowingMaxDecimalPlaces: 50}.
->
#(
'456.6699999999999590727384202182292938232421875'
'456.67000000000001591615728102624416351318359375'
'456.670000000000072759576141834259033203125'
)
因此,(d predecessor asFraction + d asFraction) / 2 printShowingMaxDecimalPlaces: 50.
和(d successor asFraction + d asFraction) / 2 printShowingMaxDecimalPlaces: 50.
之间的任何十进制表示都将被舍入到相同的浮点值(不包括边界,因为确切的扎带舍入到最近的均匀到最接近,并且此浮点具有奇怪的意义...(
范围是:
#(
'456.669999999999987494447850622236728668212890625'
'456.670000000000044337866711430251598358154296875'
)
Oracle只使用17位数字,而不会打扰进一步的数字,因为已知17位足以区分任何两个双重精度浮点值。
java更加聪明:它使用足够的数字来区分下一个代表性的浮点值。因此,将0、1、2、3或4放在位置17,甚至4.566699999999999999E2都不重要,它仍然是相同的浮点值。