I have decreased the PI from 3.1416 to 3.14, but it is still off by 0.001xxx
Using 3 digits of precision won't help. If you've got it in a library use pi loaded directly into the register. If that's not possible use a constant such as M_PI if it exists in your math libraries.
Instead, consider what you are doing very carefully:
std::sqrtf((2 * sol->R * PI) * (2 * sol->R * PI) + (sol->p_s.y - sol->w_s.y) * (sol->p_s.y - sol->w_s.y));
I don't know your scale, but consider that floating point has roughly six decimal digits of precision. (See FLT_DIG for your system-specific value). Values get converted into the correct scale as yo do the math.
So for example:
This: 123456 + 12.3456
needs to get the floating point alignment and so this:
123456.
+ 12.3456
becomes
123456.
+ 000012.3456
giving 123468.<?>, not 123468.3456 exactly, the last value becomes rounding error.
Similarly for multiplication...
Your segment of this: (2 * sol->R * PI)
looks like this to me:
2
* 695700099 (radius of our sun)
* 3.14159
is actually this:
2
* 695700???
* 3.14159
that after floating point adjustment becomes this:
000000???
* 695700???
* 000000???.?????
or, since they are carried out sequentially, becomes this:
000000002
* 695700099
===========
0
* 000000003.14159
or maybe this:
000000002
* 695700099
===========
695700099
* 000000003.14159
===========
695700099
or maybe something else entirely.
Once you've lost scale and you've done a math operation that blows away your precision, all bets are off. Maybe you got lucky and had a bit or two that happened to cover your range, or maybe you didn't.
There are some actions you can take to ensure your numbers don't get large enough to blow away your precision, but they are dependent on the operation you are doing.
For one example, averaging a ton of numbers instead of summing them all into a range that exceeds precision, you can maintain both the accumulated value and a count of values accumulated so far so you never break precision. In that case it is avg += (x/n) - (avg/n); n++; With that slight change the values you are working with are always a fraction of the original and thus always within the source precision. Unfortunately sometimes even with that, the optimizer will think it knows better than the programmer and attempt to rewrite the math, so this type of thing needs to be verified in assembly and sometimes have specific optimizations turned off around that code.
In your case, you'll need to review your math and make sure it stays inside your desired precision.