For embedded work, I rarely use floating point variables. There are a lot of good reasons to avoid it. But many years ago, David Goldberg wrote an article that covers many of the reasons why I avoid them: What Every Computer Scientist Should Know About Floating-Point Arithmetic.
In the integer domain, \$a\cdot\left(b+c\right)=a\cdot b+a\cdot c\$. But this isn't true for floating point. (It may be sufficiently close to true for some uses. But in general, you cannot bank on it.)
If you are dealing with a wide dynamic range of values, for example the mass of different particles in the universe which may vary from molecules to super-massive black holes, then by all means use floating point variables. That's what they are designed for and they work as well as is possible for such needs. If you need, and cannot plan to write your own integer versions [I will often write an ln() function designed for integers, preferring that over using a library function requiring floating point] of some complex function that only accepts and generates floating point, then that may be another good reason to use floating point. (Not because it's better, but because you don't have to the time or skills to do otherwise.)
But if your dynamic range can be managed within reasonably sized integers, that's almost always better. Also, keep in mind that in most embedded cases, you are getting analog data from ADCs (which produce integer results) or other digital inputs such as switches and are producing analog DAC outputs (consuming integers) or other digital outputs like an LED. If the data coming in is in integer format and the data going out is also in integer format, why in the world would you then want to introduce floating point during the in-between processing? It would generally be better if you would just stick to one domain, then.
Floating point has a bad problem with differences that can crop up in very unusual ways. For example, let's say you are working with values that possess a relatively wide dynamic range and you need to calculate the standard deviation:
$$\sigma=\sqrt{\frac{\Sigma \:\left(x_i-\overline{x}\right)^2}{N}}$$
The above requires first to compute \$\overline{x}\$, which requires one pass through the data, and then the above calculation requiring a second pass through the data. Often, it's not even possible to do it that way because the data is coming in fast, there's lots of it, and there's only a small bit of RAM for buffering. So one common optimization, found with a very few simple algebraic steps, uses two summations:
$$\sigma=\sqrt{\frac{\Sigma \:x_i^2}{N}-\frac{\left(\Sigma\: x_i\right)^2}{N^2}}$$
(Let's leave aside questions about full and sample populations.)
The above just requires two summations, which can be performed as "running sums" and only one pass through the data so there's no requirement to buffer it. Seems like a good idea?
Well, maybe. Maybe not.
Suppose the situation just happened to be the worst possible case. \$x_0\$ is the largest magnitude value in the set and the remaining values are magically sorted from lowest to largest, so that \$x_1\$ is the smallest value and \$x_{N-1}\$ is the 2nd to the largest value (remember, \$x_0\$ is the largest.) In this odd case, once the largest value (\$x_0\$) is summed, then the following tiny values will "round out" and won't accumulate. They are too small for the format. So the largest value encountered first causes many other values to wash out before they have a chance to accumulate into something that might have affected the lower order bits.
Now look at the above equation. It's the difference of two values. If those two terms (prior to taking the square root) are nearby values, which can be the case, then the subtraction will destroy many of the higher order bits leaving only a very few precision bits near the bottom of the format. (And still worse, should the algorithm be unfortunate enough to have generated a large running sum before encountering small values, still fewer useful precision bits may remain.) The resulting calculation may be very poor and not nearly as good as it might have been had the author been more fully aware of the pitfalls and designed for them.
Had the numbers been pre-sorted, smallest to largest, then the summations would allow the smaller values to accumulate sufficiently to impact the lower order bits of the final sum and preserve more of the precision, than otherwise. But, of course, this now means buffering the values, too.
The point here is that every time you use floating point, you have to engage yourself in analyzing the algorithm details far more than you might have to, with integers. So I generally avoid floating point whenever possible. It's just easier that way. If I use floating point, I will generate exhaustive analysis of the algorithms designed to demonstrate confidence in them across a variety of situations. (Like any engineer should do.)
There also are generic floating point testing suites, some I think available as open source code you can compile yourself, that will help vet library routines and how the compiler processes and optimizes the code. That won't address itself directly to your situation, but it can give you clues about 'gotchas' to consider when thinking through your situation.
Compilers usually first turn expressions into tree structures, and then early-optimized into DAGs (directed acyclic graphs) to include as part of a basic code block. How all these details get optimized both early on, as well as later, can vary quite a bit. And none of that optimization is going to be aware of your specific numerical situation. So the choices made by a compiler are fairly "blind" to your needs and often may not serve your situation well. (Determining that fact is your job, if you choose floating point.) Again, these caveats and/or extra analysis and evaluation time needed become yet another reason to simply avoid floating point in the first place.
So my general recommendation, without knowing specific application details, is "don't use floating point in embedded applications." Of course, granting the exceptions I discussed earlier where floating point may be required. Also, there are those trivial times when it doesn't really matter that much. For example, if you have an integer ADC value that needs to be displayed on some 7-seg LED display as a decimal point value (Celsius, for example?) and a simple expression that uses floating point saves you some "thinking" about the integer and just makes it easier without risking anything important. (I'm still tempted to just work out the integer details and avoid floating point. But time is time and if the customer is paying for it and I know this choice won't harm them, then I very well might use floating point and associated libraries at the "end point" of a chain of computations for display purposes.)