The title says it all, but I would like to know if I should use a double 1.5 for my velX and velY factor, or a float 1.5 for my velX and velY factor. Also, I would like to know if I should use a double or float for everything such as positions of entities, etc.. Thanks in advance!
A double has a wider range than a float and use more memory. In your case it properly doesn't matter but the double is often the default option.
You can read more about it here: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
Both the single-precision 32-bit
float type and double-precision 64-bit
double type can represent numbers like 1.5 exactly, with no rounding error.
(ie. as 1 * 2^0 + 1 * 2^-1, followed by 22 zeroes in the case of a
float, or 51 zeroes in the case of a
Neither one can exactly represent a number like one-fifth, 0.2, because its denominator is not a power of two. The closest you can get with a
float will be off by about 0.000 000 004, or four-billionths of a unit, and
double will get even closer.
Now I don't know about you, but I don't usually tune my game's meshes/colliders/speeds to tolerances of billionths of units, so in practice the precision limits of
float don't cause many problems in day-to-day game development calculations, as long as we're working within a few kilometers of the origin of our coordinate system - since both
double use a sliding scale of precision, staying more precise for values close to zero, and trading-off some precision to represent bigger numbers. You can consult the table in this answer for the precision available in each range.
There are a few cases where the limits do crop up though:
Exact comparisons. Whether you're using
double, don't use
if(myValue == thisTargetValue)- because even a difference of billionths of a unit like we saw above is enough to make this comparison fail. Compare using ranges instead, so your code is tolerant to some fluctuation in the tiny final digits.
Time. If you measure your time in seconds with a single-precision
float, then if your game is left running for a day you'll be in a range where you start to lose millisecond precision, and that's usually enough to make sensitive timing code go haywire.
floatis fine for accumulating time deltas like "how long has the player held the jump button," but don't use it for your global time.
doubleshould be more than sufficient for games played over human lifespans though. This type of error has led to the failure of missile defense systems, so take it seriously. ;)
Big Spaces. Once you go further than a few thousand units from the 0 point of your coordinate system, the precision limits of
floattend to become significant. You can see this in Minecraft versions before Beta 1.8 - if you walk far enough in one direction, movement becomes jumpy and the terrain starts getting weird, as the errors grow to reach the sensitivity thresholds of the algorithms being used.
3D rendering and physics engines usually work exclusively in single-precision
floattypes, so changing absolutely everything over to
doubleis generally not feasible. Instead, games with huge worlds usually solve this by breaking the world into chunks, and working with coordinates relative to the center of each chunk, rather than always in reference to the origin of the whole universe. Kerbal Space Program uses a
floatcoordinate space with a "floating origin" that moves to keep the player centered, while an underlying orbital mechanics simulation uses
doublevalues for computing the large-scale trajectories.
Accumulated Error. An error of billionths in one calculation isn't much. But if you use that as input into another calculation, then use that output as another input, on and on in a feedback loop, then the errors can accumulate and snowball out of proportion.
A common way this can happen is if you store a transformation matrix for each object, and accumulate changes to the transformation directly into that matrix, without any error-correction. This often manifests as a spinning object gradually flattening or distorting.
doubleonly delays the issue a little, because it's really a problem with our algorithm, allowing small errors to self-reinforce and magnify up to visible scales. Maintaining a separate, authoritative source value, or applying error-correction as you go, like normalizing direction vectors, can stop these errors from piling up to visible scales.
It pretty much boils down to how precise you want your world to be. Do you need to be able to move exactly 1 mm at a time or are you fine with just a rough estimate? In most cases I would go with floats as they get the job done most of the time, while also allowing for your game to potentially run faster because you only need half the amount of data in cache. If your game is very physics oriented(think Kerbal space program) then I would suggest using doubles instead.
It may also depend on 3rd party framework, engines & libraries. I.E. if you use doubles on your data structures, but your library uses floats, you may find that your doing a lot of casting. In turn, this may impact:
- Performance: This SO post suggests (down) casting isn't likely to degrade performance. That being said, sometimes microbenchmarks don't accurately portray what happens in actual production code - always profile before & after attempts to optimize.
- Precision & Accuracy: Down casting involves a loss of data. Up casting floats essentially fabricates data. Depending on your needs, this may result in precision &/or accuracy problems.
- Readability: Unless you've tweaked your compiler / IDE settings, down casts must be explicit, which can clutter up your code & reduce its readability.
- Safety: If you have tweaked your settings to permit implicit down casts, you run the risk of allowing unwanted &/or dangerous down casts to slip through.