Skip to main content

Whatever Floats Your Boat

Posted by cayhorstmann on August 14, 2011 at 5:14 PM PDT

I am in the process of revising a CS1 textbook. I made changes requested by users, added snazzy exercises and sample programs, and the publisher sent the draft out to reviewers. A couple of reviewers said in no uncertain terms that I was wrong, wrong, wrong in using double for my examples. I should use float instead. Another professor contributed a business problem set that used float where I would have used double, or, if I had been allowed, BigDecimal.

What gives? For financial calculations, float aren't so wonderful. For example,

float unitPrice = 34999.95F;
int quantity = 199;
float totalPrice = unitPrice * quantity; // Off by five cents from the correct value

Clearly, BigDecimal would be the right choice, but they are awful to use in Java.

BigDecimal unitPrice = new BigDecimal("34999.95");
BigDecimal quantity = new BigDecimal("199");
BigDecimal totalPrice = unitPrice.multiply(quantity);

In Scala, you could write BigDecimal("34999.95") * 100 . But that doesn't help me. Nobody uses Scala for their introductory course. Anyway, reviewers were adamant not to use objects and method calls too early. So, BigDecimal wasn't going to fly. But I digress.

Back to float. Even if you don't care about limited precision, they are also awkward. You have to remember to put F after each literal, and you have to cast the results of mathematical methods:

float goldenRatio = 0.5F * (1 + (float) Math.sqrt(5))

For what? Saving four bytes? In a student program that gets executed a handful of times?

I can see the use of float in a 1000 x 1000 matrix, if the added precision isn't needed, to save the storage. Does it save time? I seem to recall that in an Intel processor, when both float and double get extended unless you use strictfp. No reviewer had requested that I cover that :-)

Am I missing the boat here? Is there another reason to use float in this day and age, other than saving storage when you have a lot of them? I read through What Every Computer Scientist Should Know About Floating-Point Arithmetic, and was not enlightened. If you use float, can you tell me why?

 

 

Related Topics >>

Comments

Having been bitten by previously using float instead of ...

Having been bitten by previously using float instead of double, I now only use it in very specific circumstances (see below).

Reasons not to use float:

  • Accuracy is only about 7 significant figures: be aware that this is very poor accuracy for the kind of applications where you're using floating point (such as anything scientific/mathematical). Rounding errors can quickly accumulate giving you only 6 or even 5 significant figures, which is terrible.
  • For this and other reasons, most APIs use doubles: such as all the methods in the Math class.

Misleading 'advantages' of float:

  • 4 bytes instead of 8: this is only likely to matter in a float[] array. If you have float fields in an object, with alignment (etc.) they may save no space compared to double, or little given that objects have other memory overheads.
  • Faster: with modern processors I think the performance of double and float is very similar. If you use float, the inevitable casting to/from double will also slow your program down.

Therefore these days I say float should only be used for compressing data, such as vast float[] arrays on disk or in memory (when you don't need full accuracy). I usually convert them to/from double when loading/storing so that accuracy isn't compromised in any calculations you do with them. After all, this is how you use byte and short - in calculations they get converted to int and you have to cast them to squeeze them back into byte/short format.

I think your thinking is valid. Rarely should modern Java ...

I think your thinking is valid. Rarely should modern Java code use floats, for the reasons you bring up. My thoughts:

  • I will use floats if an API "forces" me too -- GUI libraries seem to like floats for some reason.
  • Item 48 in Bloch's Effective Java (second edition) covers the issues with exact answers pretty well.

I think you should stick with double.

Use whatever you want, and explain the reasoning in a ...

Use whatever you want, and explain the reasoning in a sidebar.  If you want to keep it short, put in a link to a blog post or whatever (For further reading...).  

These are CS students, they are (eventually) going to have to deal with the gory mess that is floats, doubles, etc.  That's easy - hard is trying to explain chars, bytes, character sets, Unicode, UTF-8, etc.  ;)

For your introductory textbook, I think you're correct, but ...

For your introductory textbook, I think you're correct, but to answer your question regarding "another reason to use float in this day and age": If you make use of the SIMD instructions available on modern chips, you can process twice as many floats as doubles at a time for many operations. Additionally, if you're doing anything GPGPU related, float operations are generally much faster on the current AMD and NVidia offerings. Now, it's true that from java, you can't directly call either simd or a gpgpu, but if you want SIMD, there are libraries which use JNI that allow you to call SIMD: http://queue.acm.org/detail.cfm?id=1945954, and if you want GPGPU, there are similar things: http://developer.amd.com/zones/java/aparapi/pages/default.aspx

Please keep the doubles.  There are good reasons not to ...

Please keep the doubles. There are good reasons not to use BigDecimal as you have mentioned, and there are good reasons not to use floating point numbers at all in financial applications, but switching to from double float in an introductory text is a bad move. Regardless, in this day, I think that doubles should would be used mudh more than floats in situations that call for floating point numbers except possibly for some embedded systems.

Disclaimer: I work with currencies other than the US ...

Disclaimer: I work with currencies other than the US dollar.
I would argue strongly to teach students that float/double should be used to model physical/mathematical processes where the margin of error is related to the number of significant digits used (ie. science applications, graphics, kinetics, etc..). For money I suggest using BigDecimal or counting cents using longs (ex: represent 100 dollars as 100 00 cents) to avoid rounding problems. With other currencies these problems become even more marked (when using tens of billions and every bit counts).
Float/double are just not the right tool for representing money, especially in the international world or when sums become huge (like the US national debt).

There are times to use float and there are times to use ...

There are times to use float and there are times to use double. - the point is to know what the current time is...

When the topic is to teach numbers and calculations (what is a +-*/, sqrt(), NaN, infinity..), then double should be fine.

The interface between them is important: conversion, mixed math, formatting.

When your students see the world through float-glasses, they will have 'surprising' results everywhere.

When they see the world through double-glasses, they might waste huge amounts of memory.

I dont know anything about float/double performance on Java ME platforms.

While we are at math: the captcha-thing for this forum asks me for some math-puzzle and it seems the answer requires some kind of int - not sure if its byte, short, int or long...

Well-stated. Float deserves a sentence or two in the same ...

Well-stated. Float deserves a sentence or two in the same paragraph where you talk about byte, short, long and BigDecimal.

Processing uses float everywhere. That decision is a source of frustration in an otherwise very usable API.

I think the interesting question for Java and future languages is when should we switch from habitually using int to habitually using long.

In teaching Java double is the way to go. You have to teach ...

In teaching Java double is the way to go. You have to teach the difference between double and float at some point (and the mathematical background of rounding mistakes, precision and so on) but for regular examples where precision is unimportant it's simply not necessary. And I never meet a person who says "change the type of all number small then 32k to a short because it's a waste". And no, double didn't necessarily save time and in bytecode float didn't really exist--all operations are done in double and casted to float (opcode f2d, d2f). (Of course this says nothing about the actual compilation in machine code.) float simply makes too much trouble, just think about

List<Double> list = Arrays.asList( 1. );

list.remove( 1.f );

System.out.println( list ); // [1.0]


There is one area where float is handy, but it's usually not important for beginners: because floats really NEED attention it's interesting to use them as a differentiator for method parameters. If you have a parameter list of two floating point variables you can minimize the problem of unintentionally interchanging them by declaring one of the variables of type float. If you declare (float, double) the caller has to pay extra attention and (1f,2) would be fine but errors like (2,1) where the arguments are swapped would cause a compiler error.

Christian, author of http://openbook.galileocomputing.de/javainsel/

Please, keep the doubles in Java Concepts as they are. ...

Please, keep the doubles in Java Concepts as they are. Otherwise what will be next? Using byte and short instead of int where possible? This will confuse my students. It suffices to mention the various types with their pros/cons when explaining data types.