View previous topic :: View next topic |
Author |
Message |
miro
Joined: 15 Jan 2011 Posts: 62
|
How to printf float32 float64.. |
Posted: Mon Aug 28, 2023 8:06 am |
|
|
Hi, we want to printf the float32/64 values and are coping with a problem.
Whatever we do the results are aprox 50 char long strings, basically a correct value, but the printf adds aprox 30-40 chars, perhaps a memory leak or wrongly set char counter in the library?? I would expect 7digits with f32 and 15 with f64 (plus minus).
Both 32/64 produce results like
9.0000006338947539475099073450937453094753031124E+00
PCD 5.112 for a dspic33fj128..
Last edited by miro on Mon Aug 28, 2023 9:14 am; edited 2 times in total |
|
|
miro
Joined: 15 Jan 2011 Posts: 62
|
|
Posted: Mon Aug 28, 2023 8:44 am |
|
|
Code: | ..
float32 a32, b32, c32;
float64 a64, b64, c64;
a32 = 157.827;
b32 = 346.384;
c32 = (a32 / b32) * 2.456433e3;
a64 = 157.827;
b64 = 346.384;
c64 = (a64 / b64) * 2.456433e3;
printf("c32 = %e\n", c32);
printf("c64 = %e\n", c64);
printf("c64 = %le\n", c64); //??
while(1){};
|
c32 = 1.1192532951166480614801912452094256877899169921E+03
c64 = 1.1192533454784300978035460616411000955849885940E+03
c64 = 1.1192533454784300978035460616411000955849885940E+03
PS: fyi - it should be (decimal math off the win calculator)
1.1192533462602198715876021987159E+03 |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19529
|
|
Posted: Mon Aug 28, 2023 10:09 am |
|
|
I remember this being reported a while ago on the f format. It was fixed
immediately. Suspect nobody tested e.
Report it to CCS, and if you do need e, then just print to a string buffer and
output only the left hand 8 characters, and then the exponent part.
You don't need 'l' the compiler treats all floats as float64 for the output
processing. Only just under 16 digits are significant in the number looks
like the output just keeps going. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9232 Location: Greensville,Ontario
|
|
Posted: Mon Aug 28, 2023 10:11 am |
|
|
You need to post the compiler version you're using !
It could be a compiler bug.... |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19529
|
|
Posted: Mon Aug 28, 2023 10:29 am |
|
|
He says 5.112 |
|
|
miro
Joined: 15 Jan 2011 Posts: 62
|
|
Posted: Mon Aug 28, 2023 11:37 am |
|
|
Yep, I think the "f" did the same (I may retest that again).
Tried to format with %m.ne but the same.
There is also f48, but the math results I got with a test were off, thus I do not bother with the f48 yet.. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19529
|
|
Posted: Mon Aug 28, 2023 11:43 am |
|
|
f is fixed in the current compiler. Will have to test if it was wrong in yours.
Contact CCS. If f is fixed already they will probably send you the fixed
file.
I don't think a lot of the f48 stuff works at all. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9232 Location: Greensville,Ontario
|
|
Posted: Mon Aug 28, 2023 2:17 pm |
|
|
sigh, I gotta trifocals.....or a bigger monitor
had to re-read the post THREE times before I saw it...
the 'split' in the bifocals was right between the dark bold numbers and the next line, also lots of 'fun' trying to walk down stairs..
this getting old isn't the fun 'THEY' said it would be.... |
|
|
miro
Joined: 15 Jan 2011 Posts: 62
|
|
Posted: Tue Aug 29, 2023 1:57 am |
|
|
..and it is not only the issue with too many digits in their printf, but the precision trouble is there as well.
For example:
..
int64_t c64i = 10000000000000;
c64i = (int64_t)(c64 * c64i);
printf("ic64 = %Ld\n", c64i);
results in:
c64 = 1.1192533449572376197389544927318638656288385391E+05
ic64 = 1119253346260219904
the precise result is (win calc bcd math)
1.1192533462602198715876021987159E+03
therefore - the simple mult/div (in my above example) gives a precise f64bit result (the internal representation), their troubled printf does not (look at the first 16 digits), the "workaround" printout via int64_t shows the precise f64 result.
Be warned - the whole float/double math stuff in this compiler would require a detailed analysis/tests before somebody starts to use it, however.. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9232 Location: Greensville,Ontario
|
|
Posted: Tue Aug 29, 2023 5:11 am |
|
|
I'm curious.....
Did you confirm that the Win calc result IS the true, real, accurate correct result ?
this...
PS: fyi - it should be (decimal math off the win calculator)
...is concerning as it show Win Calc isn't 100% perfect.
It seems there's at least one 'bug' in the Win calculator.
Compare it to several other 'calculators', maybe even online versions ?
Maybe the result is correct, but I'd expect at least comparing to three others to confirm that WinCalc can be used as an accurate 'reference'. I never sample a sensor just once and use THAT result. I take several reading to ensure the result IS true.
also
Everyone knows PICs aren't great at floating point math. Perhaps you can use 'scaled integers' ? They are far more accurate and a lot faster to compute.
Just looking at options for you to get the result you need. |
|
|
miro
Joined: 15 Jan 2011 Posts: 62
|
|
Posted: Tue Aug 29, 2023 6:09 am |
|
|
The win7/10 calculator is pretty precise, it uses 34 digits decimal math, afaik. Of course there is Wolfram Alpha and others with arbitrary precision you may compare with.
I messed a lot with double in past on various mcus, so I am aware of the limits somehow.
The 64bit double works here, it seems, the only big issue I see currently is the printf.
It should allow printing out up to say 15 decimal digits with f64.
Basic float64 math operands like "+-*/ sqrt" shall be last digit precise, the transcendental and trigo functions usually result in 1-3 last digits off, it depends on the implementation and arguments used (it is a rocket science with floating point math, indeed)..
You may use int32/64 math (fractional, scaled, etc) for almost everything when messing with typical 12-16bit sensors, of course, but soon or later you will hit into some calculations with frequency measurements (9-12digits are the raw data off any GPS disciplined system), voltage/currents (6-8 digits are the raw data people are getting today) and not having float64 is really a big pain when you do some processing like filtering/smoothing/averaging, math like standard deviation, etc etc upon those data. Not talking navigation/astronomy related, where at least float64 is a must.
And No, the dspic33/pic24 are not "slow" in float64, they are pretty useful even without an FPU. The mcus with the FPU are usually only 5-8x faster. Of course it depends on the app, but these pic24/dspic33 mcus could be quite useful in the backends of various measurement devices.. |
|
|
miro
Joined: 15 Jan 2011 Posts: 62
|
|
Posted: Tue Aug 29, 2023 7:15 am |
|
|
For example: sin(PI/5.0)
Wolfram Alpha
Win7 calculator
PCD float64
0.5877852522924731291687059546390727685976524376431459910722724807...
0.58778525229247312916870595463907
0.5877852522924738 |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19529
|
|
Posted: Tue Aug 29, 2023 8:00 am |
|
|
Seriously, that is better than I'd have expected it to be!....
C sin cos etc., are not high accuracy. However worth understanding that
an error in the fifteenth digit represents microns in any normal calculation.
It is also unavoidable, since the maths is internally only working to
just under 16 digits, and there will be rounding effects in the intermediate
maths stages.
The issue with the e format is more worrying |
|
|
miro
Joined: 15 Jan 2011 Posts: 62
|
|
Posted: Wed Aug 30, 2023 3:28 am |
|
|
For example - you want to deliver a package from pointA to pointB and your pic24/dspic driving the drone wants to know where to fly..
Code: | printf ("\n###### DISTANCE AND INITIAL BEARING\n");
float64 Alat, Alon, Blat, Blon;
float64 Er;
float64 PhiA, PhiB, XsiA, XsiB, dPhi, dLamb, a, c, d;
float64 y, x, psi, inibr;
// INPUTS
Er = 6371.3e3; // Earth radius in meters
Alon = -88.252299; // in degrees
Alat = 42.989772; // in degrees
Blon = -79.998025; // in degrees
Blat = 43.290158; // in degrees
PhiA = Alat * PI_/180.0;
PhiB = Blat * PI_/180.0;
XsiA = Alon * PI_/180.0;
XsiB = Blon * PI_/180.0;
dPhi = (Blat - Alat) * PI_/180.0;
dLamb = (Blon - Alon) * PI_/180.0;
a = sin(dPhi/2.0) * sin(dPhi/2.0);
a = a + cos(PhiA) * cos(PhiB) * sin(dLamb/2.0) * sin(dLamb/2.0);
c = 2.0 * atan2(sqrt(a), sqrt(1-a));
d = Er * c;
printf ("### Distance in meters = %e \n ", d);
y = sin(XsiB-XsiA) * cos(PhiB);
x = cos(PhiA)*sin(PhiB);
x = x - sin(PhiA)*cos(PhiB)*cos(XsiB-XsiA);
psi = atan2(y, x);
inibr = psi * 180.0/PI_ + 360.0;
inibr = fmod(inibr, 360.0);
printf ("### Initial Bearing in degrees = %e \n", inibr);
printf ("##### THIS IS THE END \n\n"); |
Provided your printf works you will get
Code: |
### Distance in meters = 6.703201695481880E+005
### Initial Bearing in degrees = 8.432511496196331E+001 |
It takes aprox 4ms in the dspic33 at 80MHz clock, not bad..
This kind of stuff works with float64 and better math precision, of course, I would not try it with float32 or some fractional integers.. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19529
|
|
Posted: Wed Aug 30, 2023 7:11 am |
|
|
Why not?.
Quite simply, no form of compass is going to give you accuracies in
billionths of a degree, and no distance measurement practical on a
flying device is going to measure to microns.
The standard float32 maths can solve calculations for aircraft tracking
that put you within a few cm of the target right across the Atlantic. On
normal drone flight distances you will be within the errors of GPS
navigation over any likely flight distance. Even the wide area augmented
systems only manage a best case of about 30cm.
You are trying to use precision beyond what is needed. |
|
|
|