From: Eric Sosman on 13 Jul 2010 12:44 On 7/13/2010 7:02 AM, Screamin Lord Byron wrote: > On 07/13/2010 03:11 AM, Arne Vajhøj wrote: >> On 12-07-2010 12:36, Screamin Lord Byron wrote: >>> On 07/12/2010 05:15 PM, markspace wrote: >>>> J.H.Kim wrote: >>>>> Hi, everyone >>>>> >>>>> My java compiler and interpreter cannot display floating point >>>>> variable. >>>>> >>>>> public class PrintTest { >>>>> public static void main(String[] args) { >>>>> double a = 3.141592; >>>>> System.out.println(a); >>>>> } >>>>> } >>>>> >>>>> The routine above does not display 3.141592. >>>> >>>> <http://docs.sun.com/source/806-3568/ncg_goldberg.html> >>>> >>>> Floating point numbers aren't exact. You can't get exactly 3.141592 out >>>> of any floating point system. Consider using BigDecimal if you need >>>> "exact" numbers. >>> >>> >>> Well, in this example there is no calculation, and significand fits >>> within 52 bits of IEEE 754 double type so it should be printed out as >>> expected: 3.141592. Please someone correct me if I'm wrong. >> >> Even though 7 decimals digits is less than 52 bits, then it is >> far from guaranteed that a 7 decimals number can be represented >> exact within 52 bit. > > I am aware there is a problem of representing fractions in any numeral > system (for example, decimal 0.1 can't be exactly represented in binary, > just as 1/3 can't be exactly represented in decimal), and here we're not > saying nothing like double d = 2. - 0.1; > > Am I wrong if I say that the literal 3.141592 is represented in memory > like this: the sign is 0, the significand is 3141592 and the exponent is > -6. Yes, you're wrong. It is represented in memory like this: - The sign is zero - The significand is 7074236280275066/9007199254740992 - The exponent is 2 - ... and the bit you're missing is that the exponent's base is not ten, but two. From this fact flow many of the consequences that mystify you. > There are no mathematical operations with this number, so it's sole > representation is in fact exact, is it not? It is not. Do the arithmetic yourself, and you'll see that the value derived from the representation is not exactly 3.141592, but about 1.6e-16 greater. > The println should print it > like it's represented, just like it prints 0.8999999999999999 as a > result of 2. - 0.1. If that's what it prints, your computer is broken (and not by just a little bit, either). -- Eric Sosman esosman(a)ieee-dot-org.invalid
From: Patricia Shanahan on 13 Jul 2010 17:33 On 7/13/2010 8:52 AM, John B. Matthews wrote: > In article<2ZGdncexkoRQ76HRnZ2dnUVZ_oednZ2d(a)earthlink.com>, > Patricia Shanahan<pats(a)acm.org> wrote: > >> Screamin Lord Byron wrote: >>> On 07/13/2010 03:11 AM, Arne Vajhøj wrote: >>>> On 12-07-2010 12:36, Screamin Lord Byron wrote: >>>>> On 07/12/2010 05:15 PM, markspace wrote: >>>>>> J.H.Kim wrote: >>>>>>> Hi, everyone >>>>>>> >>>>>>> My java compiler and interpreter cannot display floating point >>>>>>> variable. >>>>>>> >>>>>>> public class PrintTest { >>>>>>> public static void main(String[] args) { >>>>>>> double a = 3.141592; >>>>>>> System.out.println(a); >>>>>>> } >>>>>>> } >>>>>>> >>>>>>> The routine above does not display 3.141592. >>>>>> <http://docs.sun.com/source/806-3568/ncg_goldberg.html> >>>>>> >>>>>> Floating point numbers aren't exact. You can't get exactly 3.141592 out >>>>>> of any floating point system. Consider using BigDecimal if you need >>>>>> "exact" numbers. >>>>> >>>>> Well, in this example there is no calculation, and significand >>>>> fits within 52 bits of IEEE 754 double type so it should be >>>>> printed out as expected: 3.141592. Please someone correct me if >>>>> I'm wrong. >>>> Even though 7 decimals digits is less than 52 bits, then it is far >>>> from guaranteed that a 7 decimals number can be represented exact >>>> within 52 bit. >>> >>> I am aware there is a problem of representing fractions in any >>> numeral system (for example, decimal 0.1 can't be exactly >>> represented in binary, just as 1/3 can't be exactly represented in >>> decimal), and here we're not saying nothing like double d = 2. - >>> 0.1; >>> >>> Am I wrong if I say that the literal 3.141592 is represented in >>> memory like this: the sign is 0, the significand is 3141592 and the >>> exponent is -6. There are no mathematical operations with this >>> number, so it's sole representation is in fact exact, is it not? >>> The println should print it like it's represented, just like it >>> prints 0.8999999999999999 as a result of 2. - 0.1. >> >> You are wrong. 3.141592 in Java is a double literal, and double is a >> binary floating point type. See >> http://java.sun.com/docs/books/jls/third_edition/html/lexical.html#3.10.2 >> >> "The details of proper input conversion from a Unicode string >> representation of a floating-point number to the internal IEEE 754 >> binary floating-point representation are described for the methods >> valueOf of class Float and class Double of the package java.lang." >> >> The actual rule for double is described in >> http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/api/java/lang/Double.html#valueOf(java.lang.String) >> >> "Otherwise, s is regarded as representing an exact decimal value in >> the usual "computerized scientific notation" or as an exact >> hexadecimal value; this exact numerical value is then conceptually >> converted to an "infinitely precise" binary value that is then >> rounded to type double by the usual round-to-nearest rule of IEEE 754 >> floating-point arithmetic, which includes preserving the sign of a >> zero value." >> >> The compiler's input conversion for 3.141592 is necessarily inexact >> for the reason you mentioned in the first paragraph. > > I often use this online calculator to peek at the internal representation: > > <http://babbage.cs.qc.edu/IEEE-754/Decimal.html> > > For double a = 3.141592, Long.toHexString(Double.doubleToRawLongBits(a)) > yields 400921fafc8b007a, which breaks down in binary and decimal as > follows: > > sign: 0 -> + > exponent: 10000000000 = 1024 - 1023 = 1 > significand: 1.1001001000011111101011111100100010110000000001111010 > = 1.5707960000000000 > > 2^1 * 1.570796 = 3.141592, also expanded here: > > <http://en.wikipedia.org/wiki/Floating_point#Overview> > There is also a simple pure Java way of getting the actual decimal expansion. The BigDecimal(double) constructor and BigDecimal's toString are both exact: import java.math.BigDecimal; public class DemoExactDoubleOutput { public static void main(String[] args) { System.out.println(new BigDecimal(3.141592)); } } Output: 3.14159200000000016217427400988526642322540283203125 Patricia
From: Patricia Shanahan on 13 Jul 2010 17:56 On 7/12/2010 6:11 PM, Arne Vajhøj wrote: > On 12-07-2010 12:36, Screamin Lord Byron wrote: >> On 07/12/2010 05:15 PM, markspace wrote: >>> J.H.Kim wrote: >>>> Hi, everyone >>>> >>>> My java compiler and interpreter cannot display floating point >>>> variable. >>>> >>>> public class PrintTest { >>>> public static void main(String[] args) { >>>> double a = 3.141592; >>>> System.out.println(a); >>>> } >>>> } >>>> >>>> The routine above does not display 3.141592. >>> >>> <http://docs.sun.com/source/806-3568/ncg_goldberg.html> >>> >>> Floating point numbers aren't exact. You can't get exactly 3.141592 out >>> of any floating point system. Consider using BigDecimal if you need >>> "exact" numbers. >> >> >> Well, in this example there is no calculation, and significand fits >> within 52 bits of IEEE 754 double type so it should be printed out as >> expected: 3.141592. Please someone correct me if I'm wrong. > > Even though 7 decimals digits is less than 52 bits, then it is > far from guaranteed that a 7 decimals number can be represented > exact within 52 bit. > > It would be nice if println guaranteed that any literal with less > digits than what is max. due to size would be printed exactly > like the literal. But I don't think that will always be the case. I think it will if the literal has fewer than about 14 significant digits and is in the normalized range. Let the infinitely precise value of the decimal literal be x and the double representation y. According to the compiler's input conversion rules, x does round to y under the normal rounding rules. Another decimal fraction of the same or shorter length would be too different from x to also round to y. They would differ by more than the gap between doubles. They would not be possible choices for the Double.toString result. Of course, there will be many numbers with more decimal places than x that also round to y, including the one that is exactly equal to y. Double.toString should pick x, because it is the shortest decimal expansion of all those that round to y. Once the number of significant digits gets high enough there may be another value of the same or shorter length that also rounds to y. Patricia
From: Arne Vajhøj on 13 Jul 2010 19:35 On 13-07-2010 07:02, Screamin Lord Byron wrote: > Am I wrong if I say that the literal 3.141592 is represented in memory > like this: the sign is 0, the significand is 3141592 and the exponent is > -6. There are no mathematical operations with this number, so it's sole > representation is in fact exact, is it not? The println should print it > like it's represented, just like it prints 0.8999999999999999 as a > result of 2. - 0.1. Yes. Double in Java are IEEE 64 bit floating point and they are binary not decimal, so you have 1/2, 1/4 etc. not 1/10, 1/100 etc.. Arne
From: Arne Vajhøj on 13 Jul 2010 19:36 On 13-07-2010 17:33, Patricia Shanahan wrote: > On 7/13/2010 8:52 AM, John B. Matthews wrote: >> In article<2ZGdncexkoRQ76HRnZ2dnUVZ_oednZ2d(a)earthlink.com>, >> Patricia Shanahan<pats(a)acm.org> wrote: >> >>> Screamin Lord Byron wrote: >>>> On 07/13/2010 03:11 AM, Arne Vajhøj wrote: >>>>> On 12-07-2010 12:36, Screamin Lord Byron wrote: >>>>>> On 07/12/2010 05:15 PM, markspace wrote: >>>>>>> J.H.Kim wrote: >>>>>>>> Hi, everyone >>>>>>>> >>>>>>>> My java compiler and interpreter cannot display floating point >>>>>>>> variable. >>>>>>>> >>>>>>>> public class PrintTest { >>>>>>>> public static void main(String[] args) { >>>>>>>> double a = 3.141592; >>>>>>>> System.out.println(a); >>>>>>>> } >>>>>>>> } >>>>>>>> >>>>>>>> The routine above does not display 3.141592. >>>>>>> <http://docs.sun.com/source/806-3568/ncg_goldberg.html> >>>>>>> >>>>>>> Floating point numbers aren't exact. You can't get exactly >>>>>>> 3.141592 out >>>>>>> of any floating point system. Consider using BigDecimal if you need >>>>>>> "exact" numbers. >>>>>> >>>>>> Well, in this example there is no calculation, and significand >>>>>> fits within 52 bits of IEEE 754 double type so it should be >>>>>> printed out as expected: 3.141592. Please someone correct me if >>>>>> I'm wrong. >>>>> Even though 7 decimals digits is less than 52 bits, then it is far >>>>> from guaranteed that a 7 decimals number can be represented exact >>>>> within 52 bit. >>>> >>>> I am aware there is a problem of representing fractions in any >>>> numeral system (for example, decimal 0.1 can't be exactly >>>> represented in binary, just as 1/3 can't be exactly represented in >>>> decimal), and here we're not saying nothing like double d = 2. - >>>> 0.1; >>>> >>>> Am I wrong if I say that the literal 3.141592 is represented in >>>> memory like this: the sign is 0, the significand is 3141592 and the >>>> exponent is -6. There are no mathematical operations with this >>>> number, so it's sole representation is in fact exact, is it not? >>>> The println should print it like it's represented, just like it >>>> prints 0.8999999999999999 as a result of 2. - 0.1. >>> >>> You are wrong. 3.141592 in Java is a double literal, and double is a >>> binary floating point type. See >>> http://java.sun.com/docs/books/jls/third_edition/html/lexical.html#3.10.2 >>> >>> >>> "The details of proper input conversion from a Unicode string >>> representation of a floating-point number to the internal IEEE 754 >>> binary floating-point representation are described for the methods >>> valueOf of class Float and class Double of the package java.lang." >>> >>> The actual rule for double is described in >>> http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/api/java/lang/Double.html#valueOf(java.lang.String) >>> >>> >>> "Otherwise, s is regarded as representing an exact decimal value in >>> the usual "computerized scientific notation" or as an exact >>> hexadecimal value; this exact numerical value is then conceptually >>> converted to an "infinitely precise" binary value that is then >>> rounded to type double by the usual round-to-nearest rule of IEEE 754 >>> floating-point arithmetic, which includes preserving the sign of a >>> zero value." >>> >>> The compiler's input conversion for 3.141592 is necessarily inexact >>> for the reason you mentioned in the first paragraph. >> >> I often use this online calculator to peek at the internal >> representation: >> >> <http://babbage.cs.qc.edu/IEEE-754/Decimal.html> >> >> For double a = 3.141592, Long.toHexString(Double.doubleToRawLongBits(a)) >> yields 400921fafc8b007a, which breaks down in binary and decimal as >> follows: >> >> sign: 0 -> + >> exponent: 10000000000 = 1024 - 1023 = 1 >> significand: 1.1001001000011111101011111100100010110000000001111010 >> = 1.5707960000000000 >> >> 2^1 * 1.570796 = 3.141592, also expanded here: >> >> <http://en.wikipedia.org/wiki/Floating_point#Overview> >> > > There is also a simple pure Java way of getting the actual decimal > expansion. The BigDecimal(double) constructor and BigDecimal's toString > are both exact: > > import java.math.BigDecimal; > public class DemoExactDoubleOutput { > public static void main(String[] args) { > System.out.println(new BigDecimal(3.141592)); > } > } > > Output: > > 3.14159200000000016217427400988526642322540283203125 Cute. You are using the well-known flaw in that constructor as a useful feature! Arne
First
|
Prev
|
Next
|
Last
Pages: 1 2 3 4 5 Prev: POI Excel Sheet String Formats Next: How to append to textarea immediately? |