When to use float (in teaching)

Discussion in 'Java' started by Stefan Ram, May 7, 2009.

  1. Stefan Ram

    Stefan Ram Guest

    I teach some properties of the data type »double«:

    public class Main
    { public static void main( final java.lang.String[] args )
    { java.lang.System.out.println( 0.1 + 0.1 + 0.1 == 0.3 );
    java.lang.System.out.println( 1.1 * 1.1 == 1.21 ); }}

    false
    false

    . I also teach that beginners should not use the data type
    »float«, because it will only cause trouble.

    But now a student came up with this:

    public class Main
    { public static void main( final java.lang.String[] args )
    { java.lang.System.out.println( 0.1f + 0.1f + 0.1f == 0.3f );
    java.lang.System.out.println( 1.1f * 1.1f == 1.21f ); }}

    true
    true

    . So, now it looks as if double just does the wrong thing
    and as if float just does the right thing.

    How does one deal with this, when explaining, when to use
    »float« and when to use »double«?
    Stefan Ram, May 7, 2009
    #1
    1. Advertising

  2. Stefan Ram wrote:
    > I teach some properties of the data type »double«:
    >
    > public class Main
    > { public static void main( final java.lang.String[] args )
    > { java.lang.System.out.println( 0.1 + 0.1 + 0.1 == 0.3 );
    > java.lang.System.out.println( 1.1 * 1.1 == 1.21 ); }}
    >
    > false
    > false
    >
    > . I also teach that beginners should not use the data type
    > »float«, because it will only cause trouble.
    >
    > But now a student came up with this:
    >
    > public class Main
    > { public static void main( final java.lang.String[] args )
    > { java.lang.System.out.println( 0.1f + 0.1f + 0.1f == 0.3f );
    > java.lang.System.out.println( 1.1f * 1.1f == 1.21f ); }}
    >
    > true
    > true
    >
    > . So, now it looks as if double just does the wrong thing
    > and as if float just does the right thing.


    In both cases float and double are working as should be expected. Just
    because floating point types often do not represent decimal values
    exactly doesn't mean that some values are not represented exactly. In
    the case of float the result of 0.1f+0.1f+0.1f is not exactly equal to
    0.3 (because 0.3 is not exactly representable by either float or
    double). It just happens the nearest float to 0.3 (which is what 0.3f
    is) is equal to the result of 0.1f+0.1f+0.1f.

    There is a valuable place for the use of float and double in scientific
    and engineering computation. Statistics is another area where the use of
    floating point is hard to avoid. Outside of these areas they should
    mostly be avoided. Unfortunately BigInteger and BigDecimal are bit
    tedious to use due to the absence of operator overloading for these types.


    Mark Thornton
    Mark Thornton, May 7, 2009
    #2
    1. Advertising

  3. Stefan Ram

    Lew Guest

    On May 7, 12:15 pm, -berlin.de (Stefan Ram) wrote:
    >   I teach some properties of the data type »double«:
    >
    > public class Main
    > { public static void main( final java.lang.String[] args )
    >   { java.lang.System.out.println( 0.1 + 0.1 + 0.1 == 0.3  );
    >     java.lang.System.out.println(       1.1 * 1.1 == 1.21 ); }}
    >
    > false
    > false
    >
    >   . I also teach that beginners should not use the data type
    >   »float«, because it will only cause trouble.
    >
    >   But now a student came up with this:
    >
    > public class Main
    > { public static void main( final java.lang.String[] args )
    >   { java.lang.System.out.println( 0.1f + 0.1f + 0.1f == 0.3f  );
    >     java.lang.System.out.println(        1.1f * 1.1f == 1..21f ); }}
    >
    > true
    > true
    >
    >   . So, now it looks as if double just does the wrong thing
    >   and as if float just does the right thing.


    That is a completely deceptive appearance. You just happened to pick
    examples that gave that illusion. In reality, both float and double
    are doing the right thing, and you cannot count on either one to yield
    an exact comparison using '==' with values that are not exactly
    representable in finite-precision binary. In reality float has higher
    error, because in either case expected error of a term will start at 1
    ulp.

    >   How does one deal with this, when explaining, when to use
    >   »float« and when to use »double«?


    One uses double when high precision is required, which is most of the
    time. One uses float when high precision is not so necessary, as,
    say, Swing does in calculating screen positions, and when speed is
    more important than precision.

    --
    Lew
    Lew, May 7, 2009
    #3
  4. Lew wrote:
    >
    > One uses double when high precision is required, which is most of the
    > time. One uses float when high precision is not so necessary, as,
    > say, Swing does in calculating screen positions, and when speed is
    > more important than precision.
    >


    Float is used when memory is short, you need a very large number of
    values and can tolerate the lower precision. The performance advantage
    is modest (and often more a result of fitting more values in the
    processor cache than increased speed of the basic operation).
    Any exception to this is with GPUs where float is fast but double either
    slow or non existent. However this doesn't (yet) apply directly to Java.

    Mark Thornton
    Mark Thornton, May 7, 2009
    #4
  5. Stefan Ram

    Lew Guest

    Christian wrote:
    > Also a situtation where float is preferred for me to double:
    > A volatile float is written atomic  [sic] while a volatile double is not!


    That is totally not true.

    Volatile doubles are written atomically. JLS 17.7:
    > Writes and reads of volatile long and double values are always atomic.


    --
    Lew
    Lew, May 7, 2009
    #5
  6. Lew wrote:
    > Christian wrote:
    >> Also a situtation where float is preferred for me to double:
    >> A volatile float is written atomic [sic] while a volatile double is not!

    >
    > That is totally not true.
    >
    > Volatile doubles are written atomically. JLS 17.7:
    >> Writes and reads of volatile long and double values are always atomic.


    It was true of some early JVMs.

    http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4023233

    Note that despite what it says in that bug report, this has been fixed.

    Mark Thornton
    Mark Thornton, May 7, 2009
    #6
  7. Stefan Ram

    Lew Guest

    Christian wrote:
    >>> Also a situtation where float is preferred for me to double:
    >>> A volatile float is written atomic  [sic] while a volatile double is not!

    >


    Lew wrote:
    >> That is totally not true.

    >
    >> Volatile doubles are written atomically.  JLS 17.7:
    >>> Writes and reads of volatile long and double values are always atomic.

    >


    Mark Thornton wrote:
    > It was true of some early JVMs.
    >
    > http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4023233
    >
    > Note that despite what it says in that bug report, this has been fixed.


    That is so 20th century!

    Note that the memory model changed significantly (with Java 5) also,
    in particular with respect to the semantics of 'volatile'.

    I think it's safe to challenge on the basis of the JLS an incorrect
    statement about Java semantics irrespective of bugs that were fixed
    years and years ago. The point is that Sun's JVM and presumably every
    other one extant today conforms to the language specification
    regarding atomic reads and writes of volatile longs and doubles.

    As Java developers we have to go by the specification, not by bugs in
    its implementations. Those that rely on violations of the
    specification risk having their code break when the bug is fixed, as,
    say, Apache commons-lang did in tbeir "enum" implementation prior to
    Java 5 that broke when Sun fixed the bug (and Apache refused to fix
    it). Java programmers have a right to expect Java implementations to
    conform to the specification.

    That is moot here, anyway, since volatile actually works as specified
    in this matter: reads and writes of volatile longs and doubles are
    atomic. To state otherwise does a huge disservice to those who might
    not know better.

    --
    Lew
    Lew, May 7, 2009
    #7
  8. Stefan Ram

    Lew Guest

    On May 7, 5:40 pm, Lew <> wrote:
    > Those that rely on violations of the
    > specification risk having their code break when the bug is fixed, as,
    > say, Apache commons-lang did in tbeir "enum" implementation prior to
    > Java 5 that broke when Sun fixed the bug (and Apache refused to fix
    > it).  Java programmers have a right to expect Java implementations to
    > conform to the specification.
    >


    I should clarify: the Apache commons-lang "enum" bug had nothing to do
    with 'volatile'. It was that certain methods in their "enum" relied
    on references to a 'class' literal causing initialization of the
    owning class. When Sun fixed that initialization bug, those Apache
    commons "enum" methods broke.

    --
    Lew
    Lew, May 7, 2009
    #8
  9. Lew wrote:
    > Christian wrote:
    >>>> Also a situtation where float is preferred for me to double:
    >>>> A volatile float is written atomic [sic] while a volatile double is not!

    >
    > Lew wrote:
    >>> That is totally not true.
    >>> Volatile doubles are written atomically. JLS 17.7:
    >>>> Writes and reads of volatile long and double values are always atomic.

    >
    > Mark Thornton wrote:
    >> It was true of some early JVMs.
    >>
    >> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4023233
    >>
    >> Note that despite what it says in that bug report, this has been fixed.

    >
    > That is so 20th century!
    >
    > Note that the memory model changed significantly (with Java 5) also,
    > in particular with respect to the semantics of 'volatile'.
    >
    > I think it's safe to challenge on the basis of the JLS an incorrect
    > statement about Java semantics irrespective of bugs that were fixed
    > years and years ago. The point is that Sun's JVM and presumably every
    > other one extant today conforms to the language specification
    > regarding atomic reads and writes of volatile longs and doubles.
    >


    Nevertheless, it can be important to check our assumptions. Long ago I
    did check for atomic assignment found that it didn't work. Just a few
    days ago I found some code that depended on the behaviour of
    Timestamp.getTime() as exhibited by JVMs up to 1.4. In 1.4, Sun changed
    the behaviour and left the documentation very confusing (especially for
    those aware of the previous behaviour).

    In this case I was just adding an historical note that there was some
    basis for believing the assignments not to be atomic, but today it is
    about as valid as suggesting that Java is slow!

    Mark Thornton
    Mark Thornton, May 7, 2009
    #9
  10. Stefan Ram

    Tom Anderson Guest

    On Thu, 7 May 2009, Stefan Ram wrote:

    > . I also teach that beginners should not use the data type
    > ?float?, because it will only cause trouble.


    Interesting. FWIW, i use doubles when i'm doing mathematics, and floats
    when i'm doing sums - which is an aphoristic way of saying that i use
    doubles when i'm doing calculations where i care about accuracy, range,
    etc, whcih is things like numerical work, data processing, whatever, and
    floats when i'm doing things like calculating a load factor for a
    hashtable, or the index of the 95th centile in an array, etc.

    tom

    --
    When I see a man on a bicycle I have hope for the human race. --
    H. G. Wells
    Tom Anderson, May 7, 2009
    #10
  11. Stefan Ram

    Stefan Ram Guest

    Thomas Pornin <> writes:
    >The usual rule is the following: compute with the most accurate
    >type you have (double) but store only as many bits as are
    >significant in your data


    This sounds good.

    However, when float is used to store data, a rank beginner
    might be confused with situations, where »3.7 is not 3.7
    anymore«:

    public class Main
    { public static void main( final java.lang.String[] args )
    { final float a = 3.7f;
    java.lang.System.out.println( a == 3.7 ); }}

    false

    And a rank beginner usually does not need to store very
    many floating point values.

    Therefore, I deem that in my classes, where I teach to rank
    beginners¹ and have very little time, it is appropriate to
    recommend not to use float at all. When any of those students
    continues to learn Java after the end of my classes he will
    eventually learn about when to use »float«.

    1) In an introductory class about C++ with about 10 students,
    I asked some years ago, who of them has ever heard the term
    »objektorientierte Programmierung« (= »object-oriented
    programming«). No hand was raised.
    Stefan Ram, May 8, 2009
    #11
  12. Stefan Ram

    Stefan Ram Guest

    -berlin.de (Stefan Ram) writes:
    >However, when float is used to store data, a rank beginner
    >might be confused with situations, where »3.7 is not 3.7
    >anymore«:


    »... confused by situations where ...«

    >And a rank beginner usually does not need to store very
    >many floating point values.


    Another point in teaching is that many beginners tend to
    believe that »float« should be used as the standard floating
    point type, just because it is /named/ »float«, which is akin
    to »floating point«.
    Stefan Ram, May 8, 2009
    #12
  13. Stefan Ram

    Lew Guest

    Mark Thornton wrote:
    > Nevertheless, it can be important to check our assumptions. Long ago I
    > did check for atomic assignment found that it didn't work. Just a few
    > days ago I found some code that depended on the behaviour of
    > Timestamp.getTime() as exhibited by JVMs up to 1.4. In 1.4, Sun changed
    > the behaviour and left the documentation very confusing (especially for
    > those aware of the previous behaviour).


    All right, I'll bite. What was the previous behavior, and how did it change
    in Java 1.4?

    > In this case I was just adding an historical note that there was some
    > basis for believing the assignments not to be atomic, but today it is
    > about as valid as suggesting that Java is slow!


    --
    Lew
    Lew, May 8, 2009
    #13
  14. Thomas Pornin wrote:
    > It shall be noted that on some architectures, including x86 CPU in
    > 32-bit mode, floating-point computations are performed with an
    > internal 80-bit format(**), regardless of whether operands were
    > initially floats or doubles.


    Doesn't strictfp require limiting the computation to be purely 32- or
    64-bit?
    "Within an FP-strict expression, all intermediate values must be
    elements of the float value set or the double value set" (JLS 3 §15.4)

    --
    Beware of bugs in the above code; I have only proved it correct, not
    tried it. -- Donald E. Knuth
    Joshua Cranmer, May 8, 2009
    #14
  15. Stefan Ram

    Nigel Wade Guest

    Lew wrote:


    > One uses double when high precision is required, which is most of the
    > time. One uses float when high precision is not so necessary, as,
    > say, Swing does in calculating screen positions, and when speed is
    > more important than precision.
    >


    Or if memory requirements dictate that the overhead of 64bit rather than 32bit
    data is significant. For most programming applications these days this won't be
    an issue. However, if you have to process very large arrays of real numbers it
    could become significant, or are working on a system with very restricted
    memory. There may also be cases where it's necessary/desirable to reduce
    accuracy down to float before performing I/O over restricted bandwidth
    transports, but still perform all the internal arithmetic as double.

    The days when double was a luxury to be avoided unless essential have thankfully
    passed. I don't see any reason not to use double as the default, and only use
    float if necessary.

    --
    Nigel Wade
    Nigel Wade, May 8, 2009
    #15
  16. Stefan Ram

    Nigel Wade Guest

    Christian wrote:

    > Stefan Ram schrieb:
    >> I teach some properties of the data type »double«:
    >>
    >> public class Main
    >> { public static void main( final java.lang.String[] args )
    >> { java.lang.System.out.println( 0.1 + 0.1 + 0.1 == 0.3 );
    >> java.lang.System.out.println( 1.1 * 1.1 == 1.21 ); }}
    >>
    >> false
    >> false
    >>
    >> . I also teach that beginners should not use the data type
    >> »float«, because it will only cause trouble.

    >
    > imho this is a bad thing to tell...
    > Its like telling "Don't use int because it will only give you trouble
    > , always use long"
    >


    This is a false comparison. Short, int and long all have identical accuracy, the
    only difference is in their range. If the data you need to process can be held
    in an int you might as well use an int, there is nothing whatever to be gained
    by using long. This is most definitely not the case when dealing with floating
    point numbers.

    >
    > For most applications (as in 99% of all I see) float is more than enough
    > for floating point computations.


    But why use float at all? Unless there is a compelling reason to do so (speed,
    memory limitations) why not just use double as the default? There is no good
    reason not to. Starting off by learning to use float gets you into the habit of
    using float and may have serious repercussions at some later date.

    > And as one usually uses int and it
    > doesn't matter if you use long instead ... in some applications you are
    > just better off with using int or short or byte where applicable ...
    >
    >
    > There are 2 situations where double really starts to be useful ...
    > 1. very high numbers ... and you don't want to use BigInt and co...


    Or very small numbers

    > 2. high numbers that need high precicision ... if the number is in the
    > Billions and you still need precicion behind the comma ...


    any number that requires higher precision, it's not a function of the magnitude
    unless it exceeds the exponent limits of float.

    >
    > 2. sometimes happens i.e. if very large numbers are multiplied with very
    > small ones.. like a * a^-1
    > 1. is rather rare...


    or when calculating the difference between a large and small number etc.

    In fact, you might as well just use double everywhere, and only use float when
    it's required...

    --
    Nigel Wade
    Nigel Wade, May 8, 2009
    #16
  17. Lew wrote:
    > Mark Thornton wrote:
    >> Nevertheless, it can be important to check our assumptions. Long ago I
    >> did check for atomic assignment found that it didn't work. Just a few
    >> days ago I found some code that depended on the behaviour of
    >> Timestamp.getTime() as exhibited by JVMs up to 1.4. In 1.4, Sun
    >> changed the behaviour and left the documentation very confusing
    >> (especially for those aware of the previous behaviour).

    >
    > All right, I'll bite. What was the previous behavior, and how did it
    > change in Java 1.4?
    >
    >> In this case I was just adding an historical note that there was some
    >> basis for believing the assignments not to be atomic, but today it is
    >> about as valid as suggesting that Java is slow!

    >


    Prior to 1.4 Timestamp.getTime() always returned a multiple of 1000;
    that is an exact second. The fraction was then obtained from the
    getNanoseconds method. From 1.4 the getTime() method returns
    nanoseconds/1000000. The value returned by getNanoseconds hasn't
    changed, so code that relied on the pre 1.4 behaviour tends to get an
    overall time where the fractional seconds are counted twice.

    I suspect this change resulted from an effort to reduce the problems
    arising from mixing java.util.Date with java.sql.Timestamp (notably
    comparisons didn't work properly).

    Mark Thornton
    Mark Thornton, May 8, 2009
    #17
  18. Stefan Ram

    Lew Guest

    On May 8, 4:14 pm, Mark Thornton <> wrote:
    > Lew wrote:
    > > Mark Thornton wrote:
    > >> Nevertheless, it can be important to check our assumptions. Long ago I
    > >> did check for atomic assignment found that it didn't work. Just a few
    > >> days ago I found some code that depended on the behaviour of
    > >> Timestamp.getTime() as exhibited by JVMs up to 1.4. In 1.4, Sun
    > >> changed the behaviour and left the documentation very confusing
    > >> (especially for those aware of the previous behaviour).

    >
    > > All right, I'll bite.  What was the previous behavior, and how did it
    > > change in Java 1.4?

    >
    > >> In this case I was just adding an historical note that there was some
    > >> basis for believing the assignments not to be atomic, but today it is
    > >> about as valid as suggesting that Java is slow!

    >
    > Prior to 1.4 Timestamp.getTime() always returned a multiple of 1000;
    > that is an exact second. The fraction was then obtained from the
    > getNanoseconds method. From 1.4 the getTime() method returns
    > nanoseconds/1000000. The value returned by getNanoseconds hasn't
    > changed, so code that relied on the pre 1.4 behaviour tends to get an
    > overall time where the fractional seconds are counted twice.
    >
    > I suspect this change resulted from an effort to reduce the problems
    > arising from mixing java.util.Date with java.sql.Timestamp (notably
    > comparisons didn't work properly).


    Looking at the Javadocs for the Java 6 version of java.sql.Timestamp
    <http://java.sun.com/javase/6/docs/api/java/sql/Timestamp.html>
    I see:
    > Note: This type is a composite of a java.util.Date and a separate nanoseconds value.
    > Only integral seconds are stored in the java.util.Date component.


    Since the change you describe for java.sql.Timestamp is a change in
    specification, then my earlier arguments against reliance on bugs do
    not apply to this case. Relying on an obsolete specification is not a
    programmer's right. It's like relying on pre-Java 5 code that has a
    variable or method named 'enum' and being angry that it violates Java
    5's rules.

    Apache commons-lang relied on a class-initialization bug that violated
    the JLS extant at the time they relied on it, and when the bug was
    fixed, Apache refused to correct their mistake. That's a horse of a
    different color.

    Also, since this is an API class, not part of the Java language
    itself, and not mentioned in the JLS, my arguments about reliance on
    the JLS don't apply to this case. Javadocs are generated from the
    implementation of an API, and therefore are the product of an
    interpretation of the specification for that API, not the
    specification itself. There can be, and clearly sometimes are, errors
    in the implementation of Javadocs just as in the Java source itself.

    I am claiming that Java programmers have a right to rely on the JLS
    for the version of Java we're using. The JLS is the rigorous,
    normative description of Java's rules. I am also claiming that
    violating those rules just because a bug happens to let you do so is
    extremely bad practice.

    --
    Lew
    Lew, May 8, 2009
    #18
  19. Stefan Ram

    Roedy Green Guest

    On 7 May 2009 16:15:41 GMT, -berlin.de (Stefan Ram) wrote,
    quoted or indirectly quoted someone who said :

    >{ public static void main( final java.lang.String[] args )
    > { java.lang.System.out.println( 0.1f + 0.1f + 0.1f == 0.3f );
    > java.lang.System.out.println( 1.1f * 1.1f == 1.21f ); }}


    Floats are for measuring desk sizes. It does not matter if the desk
    is 143.99998 cm or 143.0 cm or 143.0002. You can't tell such desks
    apart for any practical purpose. If you start treating floats like
    currency you are in trouble. They are not SUPPOSED to add up to the
    penny, just get the approximate answer over a wide range of
    magnitudes.

    See http://mindprod.com/jgloss/floatingpoint.html


    Perhaps an analogy fretting over the inability of floats to add up
    perfectly would be like judging Britney Spears for ability to do
    carpentry. That is not what she is for. It is utterly preposterous to
    hire her to remodel your bathroom, so judging her on that ability
    makes no sense.

    --
    Roedy Green Canadian Mind Products
    http://mindprod.com

    "Species evolve exactly as if they were adapting as best they could to a changing world, and not at all as if they were moving toward a set goal."
    ~ George Gaylord Simpson
    Roedy Green, May 9, 2009
    #19
  20. Stefan Ram

    Tom Anderson Guest

    On Thu, 7 May 2009, Patricia Shanahan wrote:

    > Tom Anderson wrote:
    >> On Thu, 7 May 2009, Stefan Ram wrote:
    >>
    >>> . I also teach that beginners should not use the data type
    >>> ?float?, because it will only cause trouble.

    >>
    >> Interesting. FWIW, i use doubles when i'm doing mathematics, and floats
    >> when i'm doing sums - which is an aphoristic way of saying that i use
    >> doubles when i'm doing calculations where i care about accuracy, range,
    >> etc, whcih is things like numerical work, data processing, whatever, and
    >> floats when i'm doing things like calculating a load factor for a
    >> hashtable, or the index of the 95th centile in an array, etc.

    >
    > What is the advantage of float for the cases where you do use it?


    Performance, of course! :)

    There's no great advantage. For me, this works as a form of documentation
    - whenever i see a float, i know it's something sums-ish rather than
    mathematical.

    tom

    --
    drink beer and forget about gods. -- derslangerman
    Tom Anderson, May 9, 2009
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Andy
    Replies:
    7
    Views:
    6,238
    Roedy Green
    May 10, 2004
  2. bd
    Replies:
    0
    Views:
    604
  3. Carsten Fuchs
    Replies:
    45
    Views:
    1,504
    James Kanze
    Oct 8, 2009
  4. Simon Andrews

    When to "use strict" when teaching?

    Simon Andrews, Feb 2, 2004, in forum: Perl Misc
    Replies:
    25
    Views:
    496
    Brian McCauley
    Feb 11, 2004
  5. Stefan Ram

    Teaching Java, teaching what?

    Stefan Ram, Dec 8, 2013, in forum: Java
    Replies:
    57
    Views:
    500
    Ali Sh
    Dec 18, 2013
Loading...

Share This Page