harmony-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Shi Jun Zhang <chancedr...@gmail.com>
Subject Re: [classlib][luni]Float.toString - inaccuracy in the last digit
Date Thu, 16 Sep 2010 03:31:56 GMT
Hi,

I'm curious whether the implementation in Harmony is wrong or RI just
doesn't follow the spec.

Here is the spec for java.lang.Float.toString(float f)

public static String *toString*(float f)

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

   - If the argument is NaN, the result is the string "NaN".
   - 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*:
      - 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".
      - 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".
      - 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*.
      - 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 10
      *n* <= *m* < 10*n*+1; then let *a* be the mathematically exact
      quotient of *m* and 10*n* 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).

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.

To create localized string representations of a floating-point value, use
subclasses of NumberFormat.

 *Parameters:*f - the float to be converted. *Returns:*a string
representation of the argument. Please notice the words in red, "as many,
but only as many". In Mohan's case, the binary value for float 6.0214271E18f
is 01011110 10100111 00100000 11010000 and its exact decimal value is
6.021427051003641856E18, should the string representation be "6.021427E18"
or "6.0214271E18" ?

Let's look at the following 3 closest float value.
Hex
Binary                                                             Decimal
0x5EA720CF        01011110 10100111 00100000 11001111
6.021426501247827968E18
0x5EA720D0        01011110 10100111 00100000 11010000
6.021427051003641856E18
0x5EA720D1        01011110 10100111 00100000 11010001
6.021427600759455744E18

The argument f is 6.021427051003641856E18. When x is 6.0214271E18, f is the
float value nearest to x. When x is 6.021427E18, f is still the float value
nearest to x. When x is 6.02143E18, f is NOT the float value nearest to x.
So as my understanding, "6.021427E18" is the string should be returned, it
contains "as many, but only as many" digits to represent the float value f.
Is there any thing that i misunderstand?

On Wed, Jul 28, 2010 at 1:33 AM, Mohanraj Loganathan
<mohanraj.l@gmail.com>wrote:

> Following test[1] fails in Harmony. But passes in RI.
>
> [1] test:
>                float r=6.0214271E18f;
>                String s=Float.toString(r);
>                assertEquals("6.0214271E18",s);
> Harmony prints: 6.021427E18  (note '1' is missing from the converted
> string)
>
> When i looked into the implementation of harmony, i come to know its a
> limitation to the algorithm implemented in Harmony (Printing
> Floating-Point Numbers Quickly and Accurately, Robert G. Burger, and
> R. Kent Dybvig, Programming Language Design and Implementation (PLDI)
> 1996, pp.108-116)
>
>
> https://svn.apache.org/repos/asf/harmony/enhanced/java/branches/java6/classlib/modules/luni/src/main/native/luni/shared/dblparse.c
>
> function:
> java_org_apache_harmony_luni_util_NumberConverter_bigIntDigitGeneratorInstImpl
>
> I am clue-less to find the flaw in the implementation. Any comments
> from experts of this area?
>
> I will raise a JIRA for this issue.
>
> Thanks and Regards,
> Mohan
>



-- 
Shi Jun Zhang

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message