86

In every place I've looked, it says that double is superior to float in almost every way. float has been made obsolete by double in Java, so why is it still used?

I program a lot with Libgdx, and they force you to use float (deltaTime, etc.), but it seems to me that double is just easier to work with in terms of storage and memory.

I also read When do you use float and when do you use double, but if float is really only good for numbers with a lot of digits after the decimal point, then why can't we just use one of the many variations of double?

Is there any reason as to why people insist on using floats even though it doesn't really have any advantages anymore? Is it just too much work to change it all?

Eames
  • 885
  • 1
  • 6
  • 9

6 Answers6

170

LibGDX is a framework mostly used for game development.

In game development you usually have to do a whole lot of number crunching in real-time and any performance you can get matters. That's why game developers usually use float whenever float precision is good enough.

The size of the FPU registers in the CPU is not the only thing you need to consider in this case. In fact most of the heavy number crunching in game development is done by the GPU, and GPUs are usually optimized for floats, not doubles.

And then there is also:

  • memory bus bandwidth (how fast you can shovel data between RAM, CPU and GPU)
  • CPU cache (which makes the previous less necessary)
  • RAM
  • VRAM

which are all precious resources of which you get twice as much when you use 32bit float instead of 64bit double.

Philipp
  • 23,488
58

Floats use half as much memory as doubles.

They may have less precision than doubles, but many applications don't require precision. They have a larger range than any similarly-sized fixed point format. Therefore, they fill a niche that needs wide ranges of numbers but does not need high precision, and where memory usage is important. I've used them for large neural network systems in the past, for example.

Moving outside of Java, they're also widely used in 3D graphics, because many GPUs use them as their primary format - outside of very expensive NVIDIA Tesla / AMD FirePro devices, double-precision floating point is very slow on GPUs.

Pabru
  • 113
Jules
  • 17,880
  • 2
  • 38
  • 65
48

Backwards Compatibility

This is the number one reason for keeping behavior in an already existing language/library/ISA/etc.

Consider what would happen if they took floats out of Java. Libgdx (and thousands of other libraries and programs) wouldn't work. It's going to take a lot of effort to get everything updated, quite possibly years for many projects (just look at the backwards compatibility-breaking Python 2 to Python 3 transition). And not everything will be updated, some things will be broken forever because the maintainers abandoned them, perhaps sooner than they would have because it would take more effort than they want to update, or because it's no longer possible to accomplish what their software was supposed to do.

Performance

64 bit doubles take twice the memory and are almost always slower to process than 32 bit floats (the very rare exceptions being where 32 bit float capability is expected to be used so rarely or not at all, that no effort was made to optimize for them. Unless you're developing for specialized hardware, you won't experience this in the near future.)

Especially relevant to you, Libgdx is a game library. Games have a tendency to be more performance sensitive than most software. And gaming graphics cards (i.e. AMD Radeon and NVIDIA Geforce, not FirePro or Quadro) tend to have very weak 64 bit floating point performance. Courtesy of Anandtech, here's how double precision performance compares to single precision performance on some of AMD's and NVIDIA's top gaming cards available (as of early 2016)

AMD
Card    R9 Fury X      R9 Fury       R9 290X    R9 290
FP64    1/16           1/16          1/8        1/8

NVIDIA Card GTX Titan X GTX 980 Ti GTX 980 GTX 780 Ti FP64 1/32 1/32 1/32 1/24

Note that the R9 Fury and GTX 900 series are newer than the R9 200 and GTX 700 series, so relative performance for 64 bit floating point is decreasing. Go back far enough and you'll find the GTX 580, which had a 1/8 ratio like the R9 200 series.

1/32 of the performance is a pretty big penalty to pay if you have a tight time constraint and don't gain much by using the larger double.

8bittree
  • 5,676
  • 3
  • 29
  • 38
37

Atomic operations

In addition to what others have already said, a Java-specific disadvantage of double (and long) is that assignments to 64-bit primitive types are not guaranteed to be atomic. From the Java Language Specification, Java SE 8 Edition, page 660 (emphasis added):

17.7 Non-atomic Treatment of double and long

For the purposes of the Java programming language memory model, a single write to a non-volatile long or double value is treated as two separate writes: one to each 32-bit half. This can result in a situation where a thread sees the first 32 bits of a 64-bit value from one write, and the second 32 bits from another write.

Yuck.

To avoid this, you have to declare the 64-bit variable with the volatile keyword, or use some other form of synchronization around assignments.

3

It seems other answers missed one important point: The SIMD architectures can process less/more data depending if they operate on double or float structs (for example, eight float values at a time, or four double values at a time).

Performance considerations summary

  • float may be faster on certain CPUs (for example, certain mobile devices).
  • float uses less memory so in huge data sets it may substantially reduce the total required memory (hard disk / RAM) and consumed bandwidth.
  • float may cause a CPU to consume less power (I cannot find a reference, but if not possible at least seems plausible) for single-precision computations compared to double precision computations.
  • float consumes less bandwidth, and in some applications that matters.
  • SIMD architectures may process as much as twice the same amount of data because usually.
  • float uses as much as half of cache memory compared to double.

Accuracy considerations summary

  • In many applications float is enough
  • double has much more precision anyway

Compatibility considerations

  • If your data has to be submitted to a GPU (for example, for a video game using OpenGL or whatever other rendering API), the floating point format is considerably faster than double (that's because GPU manufacturers try to increase the number of graphics cores, and thus they try to save as much circuitry as possible in each core, so optimizing for float allows to create GPUs with more cores inside)
  • Old GPUs and some mobile devices just cannot accept double as the internal format (for 3D rendering operations)

General tips

  • On modern desktop processors (and probably a good amount of mobile processors) you can basically assume using temporary double variables on the stack gives extra precision for free (extra precision without performance penalty).
  • Never use more precision than you need (you may not know how much precision you really need).
  • Sometimes you are just forced by the range of values (some values would be infinite if you are using float, but may be limited values if you are using double)
  • Using only float or only double greatly helps the compiler to SIMD-ify the instructions.

See comments below from PeterCordes for more insights.

0

Apart from the other reasons which were mentioned:

If you have measure data, be it pressures, flows, currents, voltages or whatever, this is often done with hardware having an ADC.

An ADC typically has 10 or 12 bits, 14 or 16 bits ones are rarer. But let's stick on the 16 bit one - if measuring around full scale, you have an accuracy of 1/65535. That means a change from 65534/65535 to 65535/65535 is just this step - 1/65535. That's roughly 1.5E-05. The accuracy of a float is around 1E-07, so a lot better. That means you don't lose anything by using float for storing these data.

If you do excessive calculations with floats, you perform lightly worse than with doubles in terms of accuracy, but often you don't need that accuracy, as you often don't care if you just measured a voltage of 2 V or 2.00002 V. Similarly, if you convert this voltage into a pressure, you don't care if you have 3 bar or 3.00003 bar.

glglgl
  • 250