是否“System.out.println(DECIMAL)”总是在代码中输出相同的DECIMAL? [英] Does "System.out.println( DECIMAL )" always output the same DECIMAL in the code?

查看:163
本文介绍了是否“System.out.println(DECIMAL)”总是在代码中输出相同的DECIMAL?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当然,
System.out.println(0.1);
输出 0.1 。但是对于任意的小数点总是这样吗?
(EXCLUDE由双精度本身产生的例子,如 System.out.println(0.10000000000000000001); 输出 0.1



当我点击 System.out.println(DECIMAL); 我想,DECIMAL被转换成二进制(double),而二进制被转换成十进制(以字符串的形式输出十进制)




想(转换1) - >二进制[B] - >(CONVERSION2) - >十进制[D2]


$ b

CONVERSION1

(在double的有效位数范围内) D1]被选择为[B]



例如[D1] 0.1 - > [B] 0x0.1999999999999a

转换2

[D2]是可以唯一地区分[B]并且具有最小数字的十进制数字。例如

例如[B] 0x0.1999999999999a - > [D2] 0.1



QUOTE Java7 API Double.toString(double d)


必须为m或a的小数部分打印多少位数?必须至少有一位数字来表示小数部分,并且除此之外还需要多少位数,以便唯一地区分参数值和类型double的相邻值。也就是说,假设x是由这种方法产生的十进制表示的精确数学值,用于有限非零参数d。那么d必须是最靠近x的double值;或者如果两个double值都等于x,那么d必须是其中的一个,而d的有效数的最低有效位必须是0。


我的问题

是[D1] = [D2] 永远是真的吗?




为什么我要问这个问题



考虑以下情况,

将用户的十进制输入保存为double - >显示该十进制



我想知道[用户的输入= display]是否有保证。

(如上所述,排除因为这个长输入是罕见的情况。)

我知道当我需要精确的算术时,我应该使用BigDecimal。但在这种情况下,我不需要精确的算术。只是希望显示与用户输入相同的小数。

解决方案

这部分取决于您对等式的定义。如果你需要确切的字符串匹配,答案是否定的。例如:

  System.out.println(0.1e-1); 

打印

  0.01 

现在假定equal意味着十进制值相等,所以 0.1e-1 0.01 是相等的。

你的双打到正常的数字(不是低于正常的,溢出或下溢)少于16个十进制数字,你是安全的。每个二进制小数的小数部分无穷大,可以用double来精确表示。为了恢复原来的,它必须是该组中最短的成员。这意味着它与相同或更短的两个最接近的十进制数之间的差异必须足够大以确保它们轮到不同的双打。要获得另一个相同或更短的长度的十进制数字,至少需要改变原始数字的一个十进制数。



如果两个十进制数相差多于一个部分在2 ^ 54,并在正常的数字范围,他们是分开太远,以映射到相同的双。



这个推理不适用于次正规数字,因为他们比正常数字的精度要低:

  System.out.println(0.123451234512345e-310); 

打印

 <$即使输入只有15个有效数字,c $ c> 1.2345123451236E-311 


Of course, System.out.println( 0.1 ); outputs 0.1. But is it always true for an arbitrary decimal? (EXCLUDE cases which result from the precision of double number itself. Such as, System.out.println( 0.10000000000000000001); outputs 0.1)

When I hit System.out.println( DECIMAL ); I think, DECIMAL is converted into binary(double) and that binary is converted into decimal (to output decimal as String)


Think about the following conversion.

decimal[D1] -> (CONVERSION1) -> binary[B] -> (CONVERSION2) -> decimal[D2]

CONVERSION1:

(within the range of significant digits of double) The nearest binary of [D1] is selected as [B]

e.g. [D1] 0.1 -> [B] 0x0.1999999999999a

CONVERSION2:

[D2] is the decimal number which can uniquely distinguish [B] and has smallest digits.

e.g. [B] 0x0.1999999999999a -> [D2] 0.1

QUOTE Java7 API Double.toString(double d)

How many digits must be printed for the fractional part of m or a? There must be at least one digit to represent the fractional part, and beyond that as many, but only as many, more digits as are needed to uniquely distinguish the argument value from adjacent values of type double. That is, suppose that x is the exact mathematical value represented by the decimal representation produced by this method for a finite nonzero argument d. Then d must be the double value nearest to x; or if two double values are equally close to x, then d must be one of them and the least significant bit of the significand of d must be 0.


My Question :

Is "[D1]=[D2]" always true?


Why I ask this Question :

Thinking about the following case,

save user's decimal input as double -> display that decimal

I'm wondering whether [ user's input = display ] is guaranteed or not.

(As mentioned above, exclude the cases which result from the precision of double number itself. Since that long input is rare case.)

I know when I need accurate arithmetic, I should use BigDecimal. But in this case, I don't need accurate arithmetic. Just want to display the same decimal as user's input.

解决方案

It depends in part on your definition of equality. If you require exact string match, the answer is no. For example:

System.out.println(0.1e-1);

prints

0.01

Now assume that "equal" means decimal value equality, so that 0.1e-1 and 0.01 are equal.

If you limit your doubles to normal numbers (not subnormal, overflow, or underflow) with less than 16 significant decimal digits, you are safe. An infinity of decimal fractions round to each binary fraction that can be exactly represented in double. To recover the original, it has to be the shortest member of that set. That means the difference between it and the two nearest decimal numbers of the same or shorter length has to be big enough to ensure that they round to different doubles. To get another decimal number of the same or shorter length requires a change of at least one decimal ulp of the original number.

If two decimal numbers differ by more than one part in 2^54, and are in the normal number range, they are too far apart to map to the same double.

This reasoning does not apply to subnormal numbers because they have less precision than normal numbers:

System.out.println(0.123451234512345e-310);

prints

1.2345123451236E-311

even though the input has only 15 significant digits.

这篇关于是否“System.out.println(DECIMAL)”总是在代码中输出相同的DECIMAL?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆