如果分数不能精确地用二进制表示,Double.toString()如何工作? [英] How does Double.toString() work if a fraction number cannot be precisely represented in binary?

查看:136
本文介绍了如果分数不能精确地用二进制表示,Double.toString()如何工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法理解Double.toString()在Java/JVM中的工作方式. 我的理解是,一般而言,分数不能用Double和Float等浮点类型精确表示.例如,206.64的二进制表示形式是206.6399999999999863575794734060764312744140625.那么(206.64).toString()怎么会返回"206.64"而不是"206.6399999999999863575794734060764312744140625"?

I am unable to understand how Double.toString() works in Java/JVM. My understanding is that in general fraction numbers cannot be represented precisely in floating point types such as Double and Float. For example, the binary representation of 206.64 would be 206.6399999999999863575794734060764312744140625. Then how come (206.64).toString() returns "206.64" instead of "206.6399999999999863575794734060764312744140625"?

Kotlin中的测试代码.

Test code in Kotlin.

@Test
fun testBigDecimalToString() {
    val value = 206.64
    val expected = "206.64"

    val bigDecimal = BigDecimal(value)

    assertEquals(expected, value.toString()) // success
    assertEquals(expected, bigDecimal.toString()) // failed. Actual: 206.6399999999999863575794734060764312744140625
}

推荐答案

打印floatdouble时看到的位数是Java的float和<默认转换规则的结果. c1>转换为小数.

The number of digits you see when a float or a double is printed is a consequence of Java’s rules for default conversion of float and double to decimal.

Java的浮点数默认格式使用最少的有效十进制数字来区分数字和附近的可表示数字. 1

Java’s default formatting for floating-point numbers uses the fewest significant decimal digits needed to distinguish the number from nearby representable numbers.1

在您的示例中,源文本中的206.64被转换为double值206.6399999999999863575794734060764364312744140625,因为在double类型可表示的所有值中,该值最接近206.64.下一个较低和下一个较高的值是206.639999999999957957870870002002068996429443359375和 206.640000000000014779288903810083866119384765625.

In your example, 206.64 in source text is converted to the double value 206.6399999999999863575794734060764312744140625, because, of all the values representable in the double type, that one is closest to 206.64. The next lower and next higher values are 206.639999999999957935870043002068996429443359375 and 206.640000000000014779288903810083866119384765625.

当打印此值时,Java只需要打印"206.64",因为这足以使我们可以从其邻居206.63999999999999999579358700436040680689962443359375和 206.640000000000014779288903810083866119384765625.请注意,从206.63999…的9s末尾开始,第一个值与206.64的差值为1.1364…,而第三个值206.64000…的差值则为.1477….因此,当Java打印"206.64"时,表示正在打印的double的值是最接近的可表示值,即206.6399999999999863575794734060764312744140625值,而不是更远的206.640000000000014779288903810083866119384765625值.

When printing this value, Java only needs to print "206.64", because that is enough that we can pick out the double value 206.6399999999999863575794734060764312744140625 from its neighbors 206.639999999999957935870043002068996429443359375 and 206.640000000000014779288903810083866119384765625. Note that, starting from the end of the 9s in 206.63999…, that first value differs from 206.64 by .1364…, whereas the third value, 206.64000…, differs by .1477…. So, when Java prints "206.64", it means the value of the double being printed is the nearest representable value, and that is the 206.6399999999999863575794734060764312744140625 value, not the farther 206.640000000000014779288903810083866119384765625 value.

1 toString(float d)部分的java.lang.float文档中找到> Java SE 10 . double文档与此类似.段落中最相关的部分为粗体:

1 The rule for Java SE 10 can be found in the documentation for java.lang.float, in the toString(float d) section. The double documentation is similar. The passage, with the most relevant part in bold, is:

返回float argument的字符串表示形式.下面提到的所有字符都是ASCII字符.

Returns a string representation of the float argument. All characters mentioned below are ASCII characters.

  • 如果参数为NaN,则结果为字符串"NaN".

  • If the argument is NaN, the result is the string "NaN".

否则,结果是一个字符串,代表参数的符号和大小(绝对值).如果符号为负,则结果的第一个字符为'-'('\u002D');如果符号为正,则结果中不显示符号字符.至于 m 的大小:

Otherwise, the result is a string that represents the sign and magnitude (absolute value) of the argument. If the sign is negative, the first character of the result is '-' ('\u002D'); if the sign is positive, no sign character appears in the result. As for the magnitude m:

  • 如果 m 为无穷大,则用字符"Infinity"表示;因此,正无穷大产生结果无穷大".而负无穷大则产生结果-无穷大".

  • If m is infinity, it is represented by the characters "Infinity"; thus, positive infinity produces the result "Infinity" and negative infinity produces the result "-Infinity".

如果 m 为零,则用字符"0.0"表示;因此,负零产生结果"-0.0".而正零则产生结果"0.0".

If m is zero, it is represented by the characters "0.0"; thus, negative zero produces the result "-0.0" and positive zero produces the result "0.0".

如果 m 大于或等于10 -3 但小于10 7 ,则表示为 m 的整数部分,无十进制形式的十进制形式,后跟"."('\u002E'),后跟一个或多个十进制数字,代表 m <的小数部分/em>.

If m is greater than or equal to 10-3 but less than 107, then it is represented as the integer part of m, in decimal form with no leading zeroes, followed by '.' ('\u002E'), followed by one or more decimal digits representing the fractional part of m.

如果 m 小于10 -3 或大于或等于10 7 ,则表示为所谓的计算机科学计数法".设 n 为唯一整数,以使10 n m < 10 n +1 ;然后让 a m 和10 n 的数学精确商,这样1≤ a < 10.然后,将幅度表示为 a 的整数部分,用一个十进制数字表示,后跟'.'('\u002E'),再用十进制数字表示 a ,后跟字母"E"('\u0045'),后跟由方法Integer.toString(int)产生的以十进制整数表示的 n .

If m is less than 10-3 or greater than or equal to 107, then it is represented in so-called "computerized scientific notation." Let n be the unique integer such that 10nm < 10n+1; then let a be the mathematically exact quotient of m and 10n so that 1 ≤ a < 10. The magnitude is then represented as the integer part of a, as a single decimal digit, followed by '.' ('\u002E'), followed by decimal digits representing the fractional part of a, followed by the letter 'E' ('\u0045'), followed by a representation of n as a decimal integer, as produced by the method Integer.toString(int).

m a 的小数部分必须打印多少个数字? 必须有至少一位数字来表示小数部分,并且除此以外,还必须要有多少个数字才能唯一地将参数值与相邻的float类型的值区分开.即,假设 x 是由此方法为有限的非零参数 f 生成的十进制表示形式所表示的精确数学值.然后 f 必须是最接近 x float值;或者,如果两个float值相等地接近 x ,则 f 必须是其中之一,并且是 f的有效位的最低有效位必须为0.

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 float. That is, suppose that x is the exact mathematical value represented by the decimal representation produced by this method for a finite nonzero argument f. Then f must be the float value nearest to x; or, if two float values are equally close to x, then f must be one of them and the least significant bit of the significand of f must be 0.

这篇关于如果分数不能精确地用二进制表示,Double.toString()如何工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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